Files
zulip/static/js/overlays.js
Aditya Jain 8f0ccdf1c9 user settings: Fix active background links when a modal is visible.
A bug caused background links to open even when a modal in the user
settings overlay was active in the foreground. This commit fixes this
by disabling mouse events for the background when the modal is active,
and restoring them as soon as the modal starts closing.

Fixes #10654.
2018-12-09 22:32:53 -08:00

227 lines
5.9 KiB
JavaScript

var overlays = (function () {
var exports = {};
var active_overlay;
var close_handler;
var open_overlay_name;
function reset_state() {
active_overlay = undefined;
close_handler = undefined;
open_overlay_name = undefined;
}
exports.is_active = function () {
return !!open_overlay_name;
};
exports.is_modal_open = function () {
return $(".modal").hasClass("in");
};
exports.info_overlay_open = function () {
return open_overlay_name === 'informationalOverlays';
};
exports.settings_open = function () {
return open_overlay_name === 'settings';
};
exports.streams_open = function () {
return open_overlay_name === 'subscriptions';
};
exports.lightbox_open = function () {
return open_overlay_name === 'lightbox';
};
exports.drafts_open = function () {
return open_overlay_name === 'drafts';
};
exports.active_modal = function () {
if (!exports.is_modal_open()) {
blueslip.error("Programming error — Called active_modal when there is no modal open");
return;
}
return $(".modal.in").attr("id");
};
exports.open_overlay = function (opts) {
popovers.hide_all();
if (!opts.name || !opts.overlay || !opts.on_close) {
blueslip.error('Programming error in open_overlay');
return;
}
if (active_overlay || open_overlay_name || close_handler) {
blueslip.error('Programming error — trying to open ' + opts.name +
' before closing ' + open_overlay_name);
return;
}
blueslip.debug('open overlay: ' + opts.name);
// Our overlays are kind of crufty...we have an HTML id
// attribute for them and then a data-overlay attribute for
// them. Make sure they match.
if (opts.overlay.attr('data-overlay') !== opts.name) {
blueslip.error('Bad overlay setup for ' + opts.name);
return;
}
open_overlay_name = opts.name;
active_overlay = opts.overlay;
opts.overlay.addClass('show');
opts.overlay.attr("aria-hidden", "false");
$('.app').attr("aria-hidden", "true");
$('.fixed-app').attr("aria-hidden", "true");
$('.header').attr("aria-hidden", "true");
close_handler = function () {
opts.on_close();
reset_state();
};
};
exports.open_modal = function (name) {
if (name === undefined) {
blueslip.error('Undefined name was passed into open_modal');
return;
}
if (exports.is_modal_open()) {
blueslip.error('open_modal() was called while ' + exports.active_modal() +
' modal was open.');
return;
}
blueslip.debug('open modal: ' + name);
$("#" + name).modal("show").attr("aria-hidden", false);
// Disable background mouse events when modal is active
$('.overlay.show').attr("style", "pointer-events: none");
// Remove previous alert messsages from modal, if exists.
$("#" + name).find(".alert").hide();
};
exports.close_overlay = function (name) {
if (name !== open_overlay_name) {
blueslip.error("Trying to close " + name + " when " + open_overlay_name + " is open.");
return;
}
if (name === undefined) {
blueslip.error('Undefined name was passed into close_overlay');
return;
}
blueslip.debug('close overlay: ' + name);
active_overlay.removeClass("show");
active_overlay.attr("aria-hidden", "true");
$('.app').attr("aria-hidden", "false");
$('.fixed-app').attr("aria-hidden", "false");
$('.header').attr("aria-hidden", "false");
if (!close_handler) {
blueslip.error("Overlay close handler for " + name + " not properly setup.");
return;
}
close_handler();
};
exports.close_active = function () {
if (!open_overlay_name) {
blueslip.warn('close_active() called without checking is_active()');
return;
}
exports.close_overlay(open_overlay_name);
};
exports.close_modal = function (name) {
if (name === undefined) {
blueslip.error('Undefined name was passed into close_modal');
return;
}
if (!exports.is_modal_open()) {
blueslip.warn('close_active_modal() called without checking is_modal_open()');
return;
}
if (exports.active_modal() !== name) {
blueslip.error("Trying to close " + name +
" modal when " + exports.active_modal() + " is open.");
return;
}
blueslip.debug('close modal: ' + name);
$("#" + name).modal("hide").attr("aria-hidden", true);
// Enable mouse events for the background as the modal closes.
$('.overlay.show').attr("style", null);
};
exports.close_active_modal = function () {
if (!exports.is_modal_open()) {
blueslip.warn('close_active_modal() called without checking is_modal_open()');
return;
}
$(".modal.in").modal("hide").attr("aria-hidden", true);
};
exports.close_for_hash_change = function () {
$(".overlay.show").removeClass("show");
reset_state();
};
exports.open_settings = function () {
overlays.open_overlay({
name: 'settings',
overlay: $("#settings_overlay_container"),
on_close: function () {
hashchange.exit_overlay();
},
});
};
exports.initialize = function () {
$("body").on("click", ".overlay, .overlay .exit", function (e) {
var $target = $(e.target);
// if the target is not the .overlay element, search up the node tree
// until it is found.
if ($target.is(".exit, .exit-sign, .overlay-content, .exit span")) {
$target = $target.closest("[data-overlay]");
} else if (!$target.is(".overlay")) {
// not a valid click target then.
return;
}
var target_name = $target.attr("data-overlay");
exports.close_overlay(target_name);
e.preventDefault();
e.stopPropagation();
});
};
return exports;
}());
if (typeof module !== 'undefined') {
module.exports = overlays;
}
window.overlays = overlays;