%# BEGIN BPS TAGGED BLOCK {{{
%#
%# COPYRIGHT:
%#
%# This software is Copyright (c) 1996-2026 Best Practical Solutions, LLC
%#                                          <sales@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/licenses/old-licenses/gpl-2.0.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 }}}
<%INIT>
return unless Menu; # In case we are in Installer mode

my $page_overflow = PageMenu->child( overflow => title => loc('More'), sort_order => 99999);
# add a child element to make sure we get a dropdown indicator
$page_overflow->child(will_be_deleted => raw_html => '');
</%INIT>
<script type="text/javascript">
var rebalanceOverflowBuffer = 10;

var rebalanceOverflowMenu = function (menuId, overflowId) {
    var toplevelMenu = jQuery(menuId);
    var overflowMenu = jQuery(overflowId);
    var availableWidth = jQuery(window).width();

    if ( menuId === '#main-navigation' ) {
        // set the right position of #topactions based on the logo size to allow for custom logos.
        // font size is calculated, to as close as possible, resemble setting in em instead of pixel.
        const logo = document.querySelector('#logo');
        if ( logo.offsetWidth == 0 ) {
            return;
        }
        document.querySelector('#topactions').style.right = 'calc(' + [logo.offsetWidth + 'px', window.getComputedStyle(logo).right, '1em'].join(' + ') + ')';

        availableWidth -= jQuery('#topactions').width() + jQuery('#logo').width();;
    }
    else if ( menuId === '#page-navigation' ) {
        availableWidth -= parseFloat(jQuery('#header h1').css('padding-left'));
        availableWidth -= parseFloat(jQuery('#page-navigation').css('right'));
        var fullWidth = availableWidth;
        jQuery('#header h1').css('width', 'auto');
        var subjectWidth = jQuery('#header h1').width();
        availableWidth -= subjectWidth;

        // in case subject is too long, set page-navigation width to 50%
        if (availableWidth < fullWidth * 0.5) {
            availableWidth = fullWidth * 0.5;
            subjectWidth = fullWidth * 0.5;
            jQuery('#header h1').css('width', subjectWidth);
        }
    }

    availableWidth -= rebalanceOverflowBuffer;

    // if the menu is too wide for the viewport, move overflow items into
    // the menu
    while (toplevelMenu.width() > availableWidth) {
        // rightmost menu item, skipping the overflow menu itself
        var item = toplevelMenu.find('li.nav-item:not('+overflowId+')').get(-1);

        // no items to overflow? odd, but visual degradation is better than
        // throwing exceptions
        if (!item) {
            break;
        }

        // remove item from main menu and add it to the overflow menu
        jQuery(item).remove();
        item.classList.remove('nav-item');
        item.classList.add('menu-item');
        item.classList.remove('dropdown');
        item.classList.add('dropend');
        const link = item.querySelector('a.nav-link');
        link.classList.remove('nav-link');
        link.classList.add('dropdown-item');

        overflowMenu.children('ul').prepend(item);
        overflowMenu.addClass('has-overflow');
    }

    // if the menu + an overflow item fits into the viewport, move
    // previously overflow items back into the top level
    while (1) {
        var item = overflowMenu.find('li').get(0);

        // no items to un-overflow
        if (!item) {
            break;
        }

        item = jQuery(item);

        // first, add a clone of the menu item back into the top level,
        // in the expected place
        var clone = item.clone();
        overflowMenu.before(clone);

        // calculate width now that we have the item back in
        var prospectiveWidth = toplevelMenu.width();

        // destroy the evidence
        clone.remove();

        if (prospectiveWidth > availableWidth) {
            break;
        }

        // remove menu item from overflow menu then add back it into the
        // toplevel menu, but specifically before the overflow (which
        // should always be the last menu item)
        item.remove();
        overflowMenu.before(item);

        item = item.get(0);
        item.classList.remove('dropend');
        item.classList.add('dropdown');
        item.classList.remove('menu-item');
        item.classList.add('nav-item');
        const link = item.querySelector('a.dropdown-item');
        link.classList.remove('dropdown-item');
        link.classList.add('nav-link');

        // if we just removed the last overflow item then hide "More"
        if (overflowMenu.find('li').length == 0) {
            overflowMenu.removeClass('has-overflow');
        }
    }

    if ( menuId === '#main-navigation' ) {
        if ( jQuery(window).width() - jQuery('#topactions').width() - toplevelMenu.width() - jQuery('#logo').width() > 80 ) {
            jQuery('#topactions input[type=search]:not(.expand)').addClass('expand');
        }
        else {
            jQuery('#topactions input[type=search].expand').removeClass('expand');
        }
    }
};

jQuery(function() {
    jQuery(window).resize(function () {
        rebalanceOverflowMenu('#main-navigation', '#li-overflow');
        rebalanceOverflowMenu('#page-navigation', '#li-page-overflow');
    });

    document.querySelectorAll('#logo img').forEach(function(img) {
        img.addEventListener('load', function() {
            if ( this.offsetWidth > 0 ) {
                rebalanceOverflowMenu('#main-navigation', '#li-overflow');
            }
        });
    });
});

registerLoadListener(function (evt) {
    if ( evt.detail.elt.classList.contains('main-container') ) {
        rebalanceOverflowMenu('#main-navigation', '#li-overflow');
        rebalanceOverflowMenu('#page-navigation', '#li-page-overflow');
    }
});

</script>
