<%INIT>
# First, Sort out the SortOrder.
my $Order = 1;
while (my $CustomFieldObj = $CustomFields->Next) { 
    $CustomFieldObj->SetSortOrder($Order++);
}
$Item->Load($Item->Id); # defeat cache

my $Move = ($Direction eq 'Down') ? 1 : -1;
my $TargetObj;
my $target_order = $Item->SortOrder + $Move;

$CustomFields->RedoSearch;
while (my $CustomFieldObj = $CustomFields->Next) { 
    my $this_order = $CustomFieldObj->SortOrder;

    # if we have an exact match, finish the loop now
    ($TargetObj = $CustomFieldObj, last) if $this_order == $target_order;

    # otherwise, we need to apropos toward the general direction
    # ... first, check the sign is correct
    next unless ($this_order - $Item->SortOrder) * $Move > 0;

    # ... next, see if we already have a candidate
    if ($TargetObj) {
        # ... if yes, compare the delta and choose the smaller one
        my $orig_delta = abs($TargetObj->SortOrder - $target_order);
        my $this_delta = abs($this_order - $target_order);
        next if $orig_delta < $this_delta;
    }

    $TargetObj = $CustomFieldObj;
}

if ($TargetObj) {
    # swap their sort order
    my ($s, $t) = ($Item->SortOrder, $TargetObj->SortOrder);
    $TargetObj->SetSortOrder($s);
    $Item->SetSortOrder($t);
    # because order changed, we must redo search for subsequent uses
    $CustomFields->RedoSearch;
}

$CustomFields->GotoFirstItem;

return($TargetObj ? 1 : 0);
</%INIT>
<%ARGS>
$Item
$Direction
$CustomFields
</%ARGS>
