import rt 3.6.4
[freeside.git] / rt / html / Widgets / SelectionBox
diff --git a/rt/html/Widgets/SelectionBox b/rt/html/Widgets/SelectionBox
new file mode 100644 (file)
index 0000000..910b20b
--- /dev/null
@@ -0,0 +1,234 @@
+%# BEGIN BPS TAGGED BLOCK {{{
+%# 
+%# COPYRIGHT:
+%#  
+%# This software is Copyright (c) 1996-2007 Best Practical Solutions, LLC 
+%#                                          <jesse@bestpractical.com>
+%# 
+%# (Except where explicitly superseded by other copyright notices)
+%# 
+%# 
+%# LICENSE:
+%# 
+%# This work is made available to you under the terms of Version 2 of
+%# the GNU General Public License. A copy of that license should have
+%# been provided with this software, but in any event can be snarfed
+%# from www.gnu.org.
+%# 
+%# This work is distributed in the hope that it will be useful, but
+%# WITHOUT ANY WARRANTY; without even the implied warranty of
+%# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+%# General Public License for more details.
+%# 
+%# You should have received a copy of the GNU General Public License
+%# along with this program; if not, write to the Free Software
+%# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+%# 02110-1301 or visit their web page on the internet at
+%# http://www.gnu.org/copyleft/gpl.html.
+%# 
+%# 
+%# CONTRIBUTION SUBMISSION POLICY:
+%# 
+%# (The following paragraph is not intended to limit the rights granted
+%# to you to modify and distribute this software under the terms of
+%# the GNU General Public License and is only of importance to you if
+%# you choose to contribute your changes and enhancements to the
+%# community by submitting them to Best Practical Solutions, LLC.)
+%# 
+%# By intentionally submitting any modifications, corrections or
+%# derivatives to this work, or any other work intended for use with
+%# Request Tracker, to Best Practical Solutions, LLC, you confirm that
+%# you are the copyright holder for those contributions and you grant
+%# Best Practical Solutions,  LLC a nonexclusive, worldwide, irrevocable,
+%# royalty-free, perpetual, license to use, copy, create derivative
+%# works based on those contributions, and sublicense and distribute
+%# those contributions and any derivatives thereof.
+%# 
+%# END BPS TAGGED BLOCK }}}
+%# The SelectionBox Widget
+%# 
+%# SYNOPSIS
+%#
+%# include javascript:
+%# <& /Widgets/SelectionBox:header &>
+%#
+%# <%init>:
+%# my $sel = $m->comp ('/Widgets/SelectionBox:new',
+%#               Action => me.html',
+%#               Name => 'my-selection',
+%#               Available => \@items,
+%#                # you can do things with @{$sel->{Current}} in the 
+%#                # OnSubmit callback
+%#               OnSubmit => sub { my $sel = shift; },
+%#               Selected => \@selected);
+%#
+%# $m->comp ('/Widgets/SelectionBox:process', %ARGS, self => $sel)
+%#
+%# where @items is an arrayref, each element is [value, label],
+%# and @selected is an arrayref of selected values from @items.
+%#
+%# and in html:
+%# <& /Widgets/SelectionBox:sow, self => $sel &>
+%#
+%# if the SelectionBox is created with AutoSave option, OnSubmit will be called
+%# on every button clicked in non-js mode.
+<%method header>
+% unless ($nojs) {
+<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/class.js"></script>
+<script type="text/javascript" src="<%$RT::WebPath%>/NoAuth/js/list.js"></script>
+% }
+<%ARGS>
+$nojs => 0
+</%ARGS>
+</%method>
+
+<%method new>
+<%init>
+$ARGS{_item_map} = {map {$_->[0] => $_->[1]} @{$ARGS{Available}}};
+return \%ARGS;
+</%init>
+</%method>
+
+<%method process>
+<%init>
+unless ($ARGS{$self->{Name}.'-Submit'}) {
+    # init
+    $self->{Current} = $self->{Selected};
+    $self->{Selected} = [];
+    return;
+}
+
+$self->{Selected} = $ARGS{$self->{Name}.'-Selected'};
+if ($self->{Selected} && !ref($self->{Selected})) {
+    $self->{Selected} = [$self->{Selected}];
+}
+
+if ($ARGS{fromjs}) {
+    $self->{Current} = $self->{Selected};
+}
+else {
+    my $current = $self->{Current} = $ARGS{$self->{Name}.'-Current'};
+    ++$self->{Modified};
+    if ($current && !ref ($current)) {
+       $current = [$current];
+    }
+
+    if ($ARGS{add}) {
+       my $choosed = $ARGS{$self->{Name}.'-Available'};
+       for my $add (ref($choosed) ? @$choosed : $choosed) {
+           next if grep { $_ eq $add } @$current;
+           push @$current, $add;
+       }
+    }
+
+    if ($ARGS{remove}) {
+       my $choosed = $ARGS{$self->{Name}.'-Selected'};
+       for my $del (ref($choosed) ? @$choosed : $choosed) {
+           @$current = map { $_ eq $del ? () : $_ } @$current;
+       }
+    }
+
+    if ($ARGS{moveup} or $ARGS{movedown}) {
+       my $offset = $ARGS{moveup} ? 1 : 0;
+       my $choosed = $ARGS{$self->{Name}.'-Selected'};
+       $choosed = [$choosed] unless ref ($choosed);
+       my $canmove = 0; # not in the cornor
+       for my $i ($ARGS{moveup} ? 0..$#{$current} : reverse 0..$#{$current}) {
+           if (grep {$_ eq $current->[$i]} @$choosed) {
+               if ($canmove) {
+                   splice (@$current, $i-$offset, 2,
+                           @{$current}[$i+1-$offset,$i-$offset]);
+               }
+           }
+           else {
+               ++$canmove;
+           }
+       }
+    }
+
+    $self->{Current} = $current;
+}
+
+@{$self->{Current}} = grep { exists $self->{_item_map}{$_} } @{$self->{Current}};
+
+if ($self->{AutoSave} or $ARGS{$self->{Name}.'-Save'}) {
+    $self->{OnSubmit}->($self);
+    delete $self->{Modified};
+}
+
+</%init>
+<%ARGS>
+$self => undef
+</%ARGS>
+
+</%method>
+
+<%method current>
+% for (@{$self->{Current}}) {
+<input type="hidden" class="hidden" name="<% $self->{Name} %>-Current" value="<%$_%>" />
+% }
+<%INIT>
+</%INIT>
+<%ARGS>
+$self => undef
+</%ARGS>
+
+</%method>
+
+<%method show>
+<form method="post" action="<%$self->{Action}%>" name="SelectionBox-<% $name %>" id="SelectionBox-<% $name %>"
+% unless ($nojs) {
+onsubmit="list_<% $name %>.selectAll();"
+% }
+>
+<input type="hidden" class="hidden" name="<% $self->{Name} %>-Submit" value="1" />
+<& SelectionBox:current, self => $self &>
+<input type="hidden" class="hidden" name="fromjs" value="0" />
+<&|/l&>Available</&>:
+<br />
+<select name="<%$name%>-Available" id="<%$name%>-Available" size="<%$size%>" multiple="multiple">
+% for (@{$self->{Available}}) {
+<option value="<% $_->[0] %>"><% $_->[1] %></option>
+% }
+</select>
+<input name="add" type="submit" class="button" value=" &rarr; " />
+<select name="<%$name%>-Selected" id="<%$name%>-Selected" size="<%$size%>" multiple="multiple">
+% for (@{$self->{Current}}) {
+<option value="<% $_ %>"
+% if (exists $selected{$_}) {
+selected="selected"
+% }
+><% $self->{_item_map}{$_} %></option>
+% }
+</select>
+ <input name="moveup" type="submit" class="button" value=" &uarr; " />
+ <input name="movedown" type="submit" class="button" value=" &darr; " />
+ <input name="remove" type="submit" class="button" value="<&|/l&>Delete</&>" />
+
+% my $caption = "";
+% unless ($self->{'AutoSave'}) {
+% if ($self->{Modified}) {
+% $caption = loc('Selections modified. Please save your changes');
+% }
+<& /Elements/Submit, Caption => loc($caption), Label => loc('Save'), Name => $name.'-Save' &>
+% }
+</form>
+
+% unless ($nojs) {
+<script type="text/javascript">
+//<![CDATA[
+var list_<%$name%> = new list(document.getElementById("SelectionBox-<% $name %>"), 0, "list_<%$name%>");
+//]]>
+</script>
+% }
+<%ARGS>
+$self => undef
+$size => 10
+$nojs => 0
+</%ARGS>
+<%INIT>
+my $name = $self->{Name};
+my %selected = map {$_ => 1} @{$self->{Selected}};
+</%INIT>
+
+</%method>