我如何检测用户何时触摸了菜单以外的东西或者它是 children?
How can I detect when a user touches something other than a menu or it's children?
我正在尝试编写一些 JavaScript 来处理下拉菜单上的触摸交互。这很好用,除了我不知道如何在用户点击菜单时隐藏菜单。
我的脚本如下:
// mark all menu items as inative
function mark_all_inactive(elem) {
elem.find(".is-active").removeClass("is-active");
elem.find("[aria-hidden=false]").attr("aria-hidden", "true");
}
// mark element as active
function mark_active(elem) {
elem.closest(".menu-list_item").addClass("is-active");
elem.siblings("[aria-hidden]").attr("aria-hidden", "false");
}
// open on touchstart
jQuery(".menu-list_item").not(".menu-list_item.-mega .menu-list_item.-parent").on("touchstart", function(e) {
if (!jQuery(this).hasClass("is-active") && jQuery(this).children("[aria-hidden]").length) {
e.preventDefault();
mark_all_inactive(jQuery(this).closest(".menu-list"));
mark_active(jQuery(this).children(".menu-list_link"));
}
});
// hide on focusout
jQuery(".menu-list").on("focusout", ".menu-list_link", function() {
var parent_item = jQuery(this).closest(".menu-list_item.-parent.is-active");
if (parent_item.length) {
// timeout required for the next element to get focus
setTimeout(function() {
if (!parent_item.find(":focus").length) {
parent_item.removeClass("is-active");
parent_item.children("[aria-hidden]").attr("aria-hidden", "true");
parent_item.closest(".menu-list_item.-parent.is-active").find(".menu-list_link").first().trigger("focusout");
}
}, 10);
}
});
如您所见,我正在使用 touchstart
添加一些 类,效果非常好。尝试删除那些 类.
时会出现问题
focusout
部分代码主要用于键盘导航,但我想对其进行调整,使其在您点击离开菜单时也能触发。
据我所知,移动浏览器通常不会在点击离开某处时触发 focusout
。这对我来说似乎很奇怪,因为你认为无论输入类型如何,从某个东西上敲击都会无礼地触发 focusout
,但这不是重点。
我查看了 touchend
,但它似乎在您抬起手指后立即启动,这不是我想要的。目标是点击一次以添加 类,然后可以将手指抬起到 select a child link(也可以包含弹出菜单,因此 re-using 相同的 touchstart
脚本)。然后,当您点击任何不是活动菜单的地方时,删除 类.
那么,关于这个问题:是否可以修改脚本的 focusout
位以适应从菜单或 children 中点击?如果没有,我将如何着手编写第二个脚本来完成该任务?
您可以在以下URL:
观看现场演示
我想通了,但我不知道这是最好的方法。将事件附加到整个文档似乎有点愚蠢,但这有效:
// hide on touch away
jQuery(document).on("touchstart", function(e) {
if (!jQuery(e.target).closest(".menu-list_item.-parent.is-active").length) {
jQuery(".menu-list_item.-parent.is-active").children("[aria-hidden]").attr("aria-hidden", "true");
jQuery(".menu-list_item.-parent.is-active").removeClass("is-active");
}
});
我正在尝试编写一些 JavaScript 来处理下拉菜单上的触摸交互。这很好用,除了我不知道如何在用户点击菜单时隐藏菜单。
我的脚本如下:
// mark all menu items as inative
function mark_all_inactive(elem) {
elem.find(".is-active").removeClass("is-active");
elem.find("[aria-hidden=false]").attr("aria-hidden", "true");
}
// mark element as active
function mark_active(elem) {
elem.closest(".menu-list_item").addClass("is-active");
elem.siblings("[aria-hidden]").attr("aria-hidden", "false");
}
// open on touchstart
jQuery(".menu-list_item").not(".menu-list_item.-mega .menu-list_item.-parent").on("touchstart", function(e) {
if (!jQuery(this).hasClass("is-active") && jQuery(this).children("[aria-hidden]").length) {
e.preventDefault();
mark_all_inactive(jQuery(this).closest(".menu-list"));
mark_active(jQuery(this).children(".menu-list_link"));
}
});
// hide on focusout
jQuery(".menu-list").on("focusout", ".menu-list_link", function() {
var parent_item = jQuery(this).closest(".menu-list_item.-parent.is-active");
if (parent_item.length) {
// timeout required for the next element to get focus
setTimeout(function() {
if (!parent_item.find(":focus").length) {
parent_item.removeClass("is-active");
parent_item.children("[aria-hidden]").attr("aria-hidden", "true");
parent_item.closest(".menu-list_item.-parent.is-active").find(".menu-list_link").first().trigger("focusout");
}
}, 10);
}
});
如您所见,我正在使用 touchstart
添加一些 类,效果非常好。尝试删除那些 类.
focusout
部分代码主要用于键盘导航,但我想对其进行调整,使其在您点击离开菜单时也能触发。
据我所知,移动浏览器通常不会在点击离开某处时触发 focusout
。这对我来说似乎很奇怪,因为你认为无论输入类型如何,从某个东西上敲击都会无礼地触发 focusout
,但这不是重点。
我查看了 touchend
,但它似乎在您抬起手指后立即启动,这不是我想要的。目标是点击一次以添加 类,然后可以将手指抬起到 select a child link(也可以包含弹出菜单,因此 re-using 相同的 touchstart
脚本)。然后,当您点击任何不是活动菜单的地方时,删除 类.
那么,关于这个问题:是否可以修改脚本的 focusout
位以适应从菜单或 children 中点击?如果没有,我将如何着手编写第二个脚本来完成该任务?
您可以在以下URL:
观看现场演示我想通了,但我不知道这是最好的方法。将事件附加到整个文档似乎有点愚蠢,但这有效:
// hide on touch away
jQuery(document).on("touchstart", function(e) {
if (!jQuery(e.target).closest(".menu-list_item.-parent.is-active").length) {
jQuery(".menu-list_item.-parent.is-active").children("[aria-hidden]").attr("aria-hidden", "true");
jQuery(".menu-list_item.-parent.is-active").removeClass("is-active");
}
});