如何禁用 jqueryUI menu() 小部件的悬停行为并添加点击事件?
How do you disable the hover behavior of the jqueryUI menu() widget and add a click event instead?
由于 ADA 要求,我必须更改一个使用 jqueryui 的 menu()
小部件的按钮,以便屏幕阅读器可以单击该按钮并获得与悬停相同的行为。
当前的行为是将鼠标悬停在按钮上,然后会出现一个下拉菜单。我想要的行为是点击事件,并删除悬停。通过点击事件,屏幕阅读器应该能够看到按钮并激活下拉菜单。
我该如何完成?
为了让这更有趣,menu()
小部件与网络表单页面结合使用,这是填充菜单的内容。所以对于网络表单,我有这个:
<div id="buy-tickets-container">
<ul id="buy-tickets-button">
<li>
<div class="submit-bttn" id="buyTicketsDropDownButtonLink"><%= BuyButtonText %></div>
<ul class="event-dates">
<asp:Repeater runat="server" ID="DateList">
<ItemTemplate>
<li><a class="date-select-link" href='<%# Eval("Href") %>'><%# Eval("Date") %> <%# Eval("PriceClass") %></a></li>
</ItemTemplate>
</asp:Repeater>
</ul>
</li>
</ul>
</div>
ascx 页面上的菜单很简单:
$('#buy-tickets-button')
.menu({
position: { my: "left top", at: "left bottom + 1" },
icons: { menu: "ui-icon-blank", submenu: "ui-icon-blank" }
});
禁用悬停行为也是完全可以接受的。我查看了 menu()
的 jqueryui api,但它没有 click()
事件。我可以实现一些我发现的删除按钮上的悬停行为的东西,$('#buy-tickets-button').unbind('mouseenter mouseleave');
,但仍然需要点击事件。而且仅仅添加一个点击事件是行不通的,主要是因为我不知道像悬停一样绑定什么...
另一个问题是这个网站将在大约 6 个月后被替换,所以我不想在这个修复上投入太多时间。那我该怎么办?
这基本上覆盖了 UI 菜单使用的一些功能。它确实使他们更多地基于点击并且它可能有点矫枉过正,但它似乎有效。我们也可以强制 blur
和 focus
对 Widget Factory 不做任何事情。
$(function() {
$.widget("custom.myMenu", $.ui.menu, {
_create: function() {
var categoryParent, html;
$(this.element).off('click mousedown mouseenter mouseleave');
this._on({
/**
* Prevent focus from sticking to links inside menu after clicking
* them (focus should always stay on UL during navigation).
*/
'mousedown .ui-menu-item > a': function(event) {
event.preventDefault();
},
/**
* Prevent focus from sticking to links inside menu after clicking
* them (focus should always stay on UL during navigation).
*/
'click .ui-state-disabled > a': function(event) {
event.preventDefault();
},
/**
* @param {jQuer.Event} event
*/
'click .ui-menu-item:has(a)': function(event) {
console.log('mine');
event.preventDefault();
var target = $(event.target).closest('.ui-menu-item');
if (!this.mouseHandled && target.not('.ui-state-disabled').length) {
this.select(event);
// Open submenu on click
if (target.has('.ui-menu').length) {
this.expand(event);
} else if (!this.element.is(':focus') &&
$(this.document[0].activeElement).closest('.ui-menu').length
) {
// Redirect focus to the menu
this.element.trigger('focus', [true]);
// If the active item is on the top level, let it stay active.
// Otherwise, blur the active item since it is no longer visible.
if (this.active && this.active.parents('.ui-menu').length === 1) { //eslint-disable-line
clearTimeout(this.timer);
}
}
}
},
/**
* @param {jQuery.Event} event
*/
'click .ui-menu-item': function(event) {
var target = $(event.currentTarget),
submenu = this.options.menus,
ulElement,
ulElementWidth,
width,
targetPageX,
rightBound;
if (target.has(submenu)) {
ulElement = target.find(submenu);
ulElementWidth = ulElement.outerWidth(true);
width = target.outerWidth() * 2;
targetPageX = target.offset().left;
rightBound = $(window).width();
if (ulElementWidth + width + targetPageX > rightBound) {
ulElement.addClass('submenu-reverse');
}
if (targetPageX - ulElementWidth < 0) {
ulElement.removeClass('submenu-reverse');
}
}
// Remove ui-state-active class from siblings of the newly focused menu item
// to avoid a jump caused by adjacent elements both having a class with a border
target.siblings().children('.ui-state-active').removeClass('ui-state-active');
this.focus(event, target);
},
/**
* @param {jQuery.Event} event
*/
'mouseleave': function(event) {
this.collapseAll(event, true);
},
/**
* Mouse leave.
*/
});
categoryParent = this.element.find('.all-category');
html = $('html');
categoryParent.remove();
if (html.hasClass('nav-open')) {
html.removeClass('nav-open');
setTimeout(function() {
html.removeClass('nav-before-open');
}, this.options.hideDelay);
}
this._super();
},
blur: function() {
return false;
},
focus: function() {
return false;
}
});
$('#buy-tickets-button')
.myMenu({
position: {
my: "left top",
at: "left bottom + 1"
},
icons: {
menu: "ui-icon-blank",
submenu: "ui-icon-blank"
}
});
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="buy-tickets-container">
<ul id="buy-tickets-button">
<li>
<div class="submit-bttn" id="buyTicketsDropDownButtonLink">
Buy Tickets
</div>
<ul class="event-dates">
<li>
<a class="date-select-link" href='#'>
03/10/20
</a>
</li>
<li>
<a class="date-select-link" href='#'>
03/11/20
</a>
</li>
<li>
<a class="date-select-link" href='#'>
03/12/20
</a>
</li>
</ul>
</li>
</ul>
</div>
由于 ADA 要求,我必须更改一个使用 jqueryui 的 menu()
小部件的按钮,以便屏幕阅读器可以单击该按钮并获得与悬停相同的行为。
当前的行为是将鼠标悬停在按钮上,然后会出现一个下拉菜单。我想要的行为是点击事件,并删除悬停。通过点击事件,屏幕阅读器应该能够看到按钮并激活下拉菜单。
我该如何完成?
为了让这更有趣,menu()
小部件与网络表单页面结合使用,这是填充菜单的内容。所以对于网络表单,我有这个:
<div id="buy-tickets-container">
<ul id="buy-tickets-button">
<li>
<div class="submit-bttn" id="buyTicketsDropDownButtonLink"><%= BuyButtonText %></div>
<ul class="event-dates">
<asp:Repeater runat="server" ID="DateList">
<ItemTemplate>
<li><a class="date-select-link" href='<%# Eval("Href") %>'><%# Eval("Date") %> <%# Eval("PriceClass") %></a></li>
</ItemTemplate>
</asp:Repeater>
</ul>
</li>
</ul>
</div>
ascx 页面上的菜单很简单:
$('#buy-tickets-button')
.menu({
position: { my: "left top", at: "left bottom + 1" },
icons: { menu: "ui-icon-blank", submenu: "ui-icon-blank" }
});
禁用悬停行为也是完全可以接受的。我查看了 menu()
的 jqueryui api,但它没有 click()
事件。我可以实现一些我发现的删除按钮上的悬停行为的东西,$('#buy-tickets-button').unbind('mouseenter mouseleave');
,但仍然需要点击事件。而且仅仅添加一个点击事件是行不通的,主要是因为我不知道像悬停一样绑定什么...
另一个问题是这个网站将在大约 6 个月后被替换,所以我不想在这个修复上投入太多时间。那我该怎么办?
这基本上覆盖了 UI 菜单使用的一些功能。它确实使他们更多地基于点击并且它可能有点矫枉过正,但它似乎有效。我们也可以强制 blur
和 focus
对 Widget Factory 不做任何事情。
$(function() {
$.widget("custom.myMenu", $.ui.menu, {
_create: function() {
var categoryParent, html;
$(this.element).off('click mousedown mouseenter mouseleave');
this._on({
/**
* Prevent focus from sticking to links inside menu after clicking
* them (focus should always stay on UL during navigation).
*/
'mousedown .ui-menu-item > a': function(event) {
event.preventDefault();
},
/**
* Prevent focus from sticking to links inside menu after clicking
* them (focus should always stay on UL during navigation).
*/
'click .ui-state-disabled > a': function(event) {
event.preventDefault();
},
/**
* @param {jQuer.Event} event
*/
'click .ui-menu-item:has(a)': function(event) {
console.log('mine');
event.preventDefault();
var target = $(event.target).closest('.ui-menu-item');
if (!this.mouseHandled && target.not('.ui-state-disabled').length) {
this.select(event);
// Open submenu on click
if (target.has('.ui-menu').length) {
this.expand(event);
} else if (!this.element.is(':focus') &&
$(this.document[0].activeElement).closest('.ui-menu').length
) {
// Redirect focus to the menu
this.element.trigger('focus', [true]);
// If the active item is on the top level, let it stay active.
// Otherwise, blur the active item since it is no longer visible.
if (this.active && this.active.parents('.ui-menu').length === 1) { //eslint-disable-line
clearTimeout(this.timer);
}
}
}
},
/**
* @param {jQuery.Event} event
*/
'click .ui-menu-item': function(event) {
var target = $(event.currentTarget),
submenu = this.options.menus,
ulElement,
ulElementWidth,
width,
targetPageX,
rightBound;
if (target.has(submenu)) {
ulElement = target.find(submenu);
ulElementWidth = ulElement.outerWidth(true);
width = target.outerWidth() * 2;
targetPageX = target.offset().left;
rightBound = $(window).width();
if (ulElementWidth + width + targetPageX > rightBound) {
ulElement.addClass('submenu-reverse');
}
if (targetPageX - ulElementWidth < 0) {
ulElement.removeClass('submenu-reverse');
}
}
// Remove ui-state-active class from siblings of the newly focused menu item
// to avoid a jump caused by adjacent elements both having a class with a border
target.siblings().children('.ui-state-active').removeClass('ui-state-active');
this.focus(event, target);
},
/**
* @param {jQuery.Event} event
*/
'mouseleave': function(event) {
this.collapseAll(event, true);
},
/**
* Mouse leave.
*/
});
categoryParent = this.element.find('.all-category');
html = $('html');
categoryParent.remove();
if (html.hasClass('nav-open')) {
html.removeClass('nav-open');
setTimeout(function() {
html.removeClass('nav-before-open');
}, this.options.hideDelay);
}
this._super();
},
blur: function() {
return false;
},
focus: function() {
return false;
}
});
$('#buy-tickets-button')
.myMenu({
position: {
my: "left top",
at: "left bottom + 1"
},
icons: {
menu: "ui-icon-blank",
submenu: "ui-icon-blank"
}
});
});
<link rel="stylesheet" href="//code.jquery.com/ui/1.12.1/themes/base/jquery-ui.css">
<link rel="stylesheet" href="/resources/demos/style.css">
<script src="https://code.jquery.com/jquery-1.12.4.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.js"></script>
<div id="buy-tickets-container">
<ul id="buy-tickets-button">
<li>
<div class="submit-bttn" id="buyTicketsDropDownButtonLink">
Buy Tickets
</div>
<ul class="event-dates">
<li>
<a class="date-select-link" href='#'>
03/10/20
</a>
</li>
<li>
<a class="date-select-link" href='#'>
03/11/20
</a>
</li>
<li>
<a class="date-select-link" href='#'>
03/12/20
</a>
</li>
</ul>
</li>
</ul>
</div>