Files
tildes/tildes/static/js/behaviors/dropdown-toggle.js
Andrew Shu ca38cd67fd Push dropdown up if it's off bottom of screen/site
Use bottom: 100% to make sure the menu does not overlap the
button (as with bottom: 0). If it overlaps the button then
that interferes with the button click handler.
2020-07-21 15:40:39 -06:00

56 lines
2.2 KiB
JavaScript

// Copyright (c) 2020 Tildes contributors <code@tildes.net>
// SPDX-License-Identifier: AGPL-3.0-or-later
// Note: unlike almost all other JS behaviors, this one does not attach to elements
// based on the presence of a data-js-* HTML attribute. This attaches to any element
// with the dropdown-toggle class so that this behavior is always applied to dropdowns.
$.onmount(".dropdown-toggle", function() {
$(this).click(function() {
var $this = $(this);
// Spectre.css's dropdown menus use the focus event to display the menu,
// but Safari and Firefox on OSX don't give focus to a <button> when it's
// clicked. More info:
// https://developer.mozilla.org/en-US/docs/Web/HTML/Element/button#Clicking_and_focus
// This should make the behavior consistent across all browsers
$this.focus();
$this.toggleClass("active");
// If toggleClass removed the class, that means that the click was on an
// already-active button, so we should hide the menu (via losing focus).
if (!$this.hasClass("active")) {
$this.blur();
return;
}
// If the menu ends up off the left edge of the screen, remove the
// .dropdown-right class so that it's aligned to the left edge of the button
// instead of the right edge
var $menu = $this.siblings(".menu").first();
$this
.parent()
.toggleClass(
"dropdown-right",
$this.offset().left + $this.width() - $menu.width() > 0
);
// If the menu extends past the bottom of the viewport, or the site footer
// overlaps the menu, push the menu above the button instead.
var menuBottom = $this.offset().top + $this.height() + $menu.height();
var viewportHeight = $(window).height();
var scrollTop = $(document).scrollTop();
var footerTop = $("#site-footer").offset().top;
$this
.parent()
.toggleClass(
"dropdown-bottom",
menuBottom > viewportHeight + scrollTop || menuBottom > footerTop
);
});
$(this).blur(function() {
$(this).removeClass("active");
});
});