%# BEGIN BPS TAGGED BLOCK {{{
%# 
%# COPYRIGHT:
%#  
%# This software is Copyright (c) 1996-2006 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., 675 Mass Ave, Cambridge, MA 02139, USA.
%# 
%# 
%# 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>
