rt 4.2.13 ticket#13852
[freeside.git] / rt / lib / RT / Interface / Web / Menu.pm
index 045df1f..3d22a15 100644 (file)
@@ -2,7 +2,7 @@
 #
 # COPYRIGHT:
 #
-# This software is Copyright (c) 1996-2012 Best Practical Solutions, LLC
+# This software is Copyright (c) 1996-2016 Best Practical Solutions, LLC
 #                                          <sales@bestpractical.com>
 #
 # (Except where explicitly superseded by other copyright notices)
@@ -57,7 +57,7 @@ use URI;
 use Scalar::Util qw(weaken);
 
 __PACKAGE__->mk_accessors(qw(
-    key title description raw_html escape_title sort_order target class
+    key title description raw_html escape_title sort_order target class attributes
 ));
 
 =head1 NAME
@@ -70,9 +70,9 @@ RT::Interface::Web::Menu - Handle the API for menu navigation
 
 Creates a new L<RT::Interface::Web::Menu> object.  Possible keys in the
 I<PARAMHASH> are L</parent>, L</title>, L</description>, L</path>,
-L</raw_html>, L<escape_title>, L</sort_order>, L</class>, L</target> and
-L</active>.  See the subroutines with the respective name below for
-each option's use.
+L</raw_html>, L<escape_title>, L</sort_order>, L</class>, L</target>,
+L<attributes>, and L</active>.  See the subroutines with the respective name
+below for each option's use.
 
 =cut
 
@@ -139,6 +139,12 @@ Get or set the frame or pseudo-target for this link. something like L<_blank>
 Gets or sets the CSS class the menu item should have in addition to the default
 classes.  This is only used if L</raw_html> isn't specified.
 
+=head2 attributes [HASHREF]
+
+Gets or sets a hashref of HTML attribute name-value pairs that the menu item
+should have in addition to the attributes which have their own accessor, like
+L</class> and L</target>.  This is only used if L</raw_html> isn't specified.
+
 =head2 path
 
 Gets or sets the URL that the menu's link goes to.  If the link
@@ -314,4 +320,59 @@ sub children {
     return wantarray ? @kids : \@kids;
 }
 
+=head2 add_after
+
+Called on a child, inserts a new menu item after it and shifts any other
+menu items at this level to the right.
+
+L<child> by default would insert at the end of the list of children, unless you
+did manual sort_order calculations.
+
+Takes all the regular arguments to L<child>.
+
+=cut
+
+sub add_after { shift->_insert_sibling("after", @_) }
+
+=head2 add_before
+
+Called on a child, inserts a new menu item at the child's location and shifts
+the child and the other menu items at this level to the right.
+
+L<child> by default would insert at the end of the list of children, unless you
+did manual sort_order calculations.
+
+Takes all the regular arguments to L<child>.
+
+=cut
+
+sub add_before { shift->_insert_sibling("before", @_) }
+
+sub _insert_sibling {
+    my $self = shift;
+    my $where = shift;
+    my $parent = $self->parent;
+    my $sort_order;
+    for my $contemporary ($parent->children) {
+        if ( $contemporary->key eq $self->key ) {
+            if ($where eq "before") {
+                # Bump the current child and the following
+                $sort_order = $contemporary->sort_order;
+            }
+            elsif ($where eq "after") {
+                # Leave the current child along, bump the rest
+                $sort_order = $contemporary->sort_order + 1;
+                next;
+            }
+            else {
+                # never set $sort_order, act no differently than ->child()
+            }
+        }
+        if ( $sort_order ) {
+            $contemporary->sort_order( $contemporary->sort_order + 1 );
+        }
+    }
+    $parent->child( @_, sort_order => $sort_order );
+}
+
 1;