fix multiple issues with ctx menu event delegation and keyboard navigation

This commit is contained in:
Nariman Jelveh 2024-06-26 00:57:12 -07:00
parent b78c83a4ab
commit 8a763eab6f
2 changed files with 30 additions and 25 deletions

View File

@ -154,14 +154,14 @@
/**
* Trigger a possible row activation whenever entering a new row.
*/
var mouseenterRow = function () {
var mouseenterRow = function (e, data) {
if (timeoutId) {
// Cancel any previous activation delays
clearTimeout(timeoutId);
}
options.enter(this);
possiblyActivate(this);
possiblyActivate(this, e, data);
},
mouseleaveRow = function () {
options.exit(this);
@ -177,7 +177,12 @@
/**
* Activate a menu row.
*/
var activate = function (row) {
var activate = function (row, e, data) {
if(mouseLocs[mouseLocs.length - 1]?.x !== undefined && mouseLocs[mouseLocs.length - 1]?.y !== undefined){
row.pageX = mouseLocs[mouseLocs.length - 1].x;
row.pageY = mouseLocs[mouseLocs.length - 1].y;
}
if (row == activeRow) {
return;
}
@ -187,7 +192,7 @@
}
options.activate(row);
options.activate(row, e, data);
activeRow = row;
};
@ -196,15 +201,15 @@
* shouldn't activate yet because user may be trying to enter
* a submenu's content, then delay and check again later.
*/
var possiblyActivate = function (row) {
var possiblyActivate = function (row, e, data) {
var delay = activationDelay();
if (delay) {
timeoutId = setTimeout(function () {
possiblyActivate(row);
possiblyActivate(row, e, data);
}, delay);
} else {
activate(row);
activate(row, e, data);
}
};
@ -327,7 +332,7 @@
return 0;
};
$menu.on('mouseenter', function(e) {
$menu.on('mouseenter', function(e, data) {
if($menu.find('.context-menu-item-active').length === 0 && $menu.find('.has-open-context-menu-submenu').length === 0)
activeRow = null;
})
@ -395,7 +400,8 @@ function UIContextMenu(options){
h += `<span class="context-menu-item-icon">${options.items[i].icon ?? ''}</span>`;
h += `<span class="context-menu-item-icon-active">${options.items[i].icon_active ?? (options.items[i].icon ?? '')}</span>`;
// label
h += `${html_encode(options.items[i].html)}`;
h += `<span class="contextmenu-label">${html_encode(options.items[i].html)}</span>`;
h += `<span class="contextmenu-label-active">${html_encode(options.items[i].html_active ?? options.items[i].html)}</span>`;
// arrow
h += `<img class="submenu-arrow" src="${html_encode(window.icons['chevron-right.svg'])}"><img class="submenu-arrow submenu-arrow-active" src="${html_encode(window.icons['chevron-right-active.svg'])}">`;
h += `</li>`;
@ -533,7 +539,12 @@ function UIContextMenu(options){
// this.activate(e);
},
// activates item when mouse enters depending on mouse position and direction
activate: function (e) {
activate: function (e, event, data) {
// make sure last recorded mouse position is the same as the current one before activating
// this is because switching contexts from iframe to window can cause the mouse position to be off
if(!data?.keyboard && (e.pageX !== window.mouseX || e.pageY !== window.mouseY)){
return;
}
// activate items
let item = $(e).closest('.context-menu-item');
// mark other menu items as inactive
@ -686,8 +697,7 @@ $(document).on('mouseenter', '.context-menu', function(e){
})
})
$(document).on('mouseenter', '.context-menu-item', function(e){
// select_ctxmenu_item(this);
$(document).on('mouseenter', '.context-menu-item', function(e, data){
})
$(document).on('mouseenter', '.context-menu-divider', function(e){
@ -695,6 +705,4 @@ $(document).on('mouseenter', '.context-menu-divider', function(e){
$(this).siblings('.context-menu-item:not(.has-open-context-menu-submenu)').removeClass('context-menu-item-active');
})
$(document)
export default UIContextMenu;

View File

@ -161,9 +161,9 @@ $(document).bind('keydown', async function(e){
return false;
}
// if right arrow is pressed, open the submenu by triggering a mouseover event
else if($('.context-menu-active .context-menu-item-active').length > 0 && (e.which === 39)){
else if($('.context-menu-active .context-menu-item-active').length > 0 && e.which === 39){
const selected_item = $('.context-menu-active .context-menu-item-active').get(0);
$(selected_item).trigger('mouseover');
$(selected_item).trigger('mouseover', {keyboard: true});
// if the submenu is open, select the first item in the submenu
if($(selected_item).hasClass('context-menu-item-submenu') === true){
$(selected_item).removeClass('context-menu-item-active');
@ -184,6 +184,7 @@ $(document).bind('keydown', async function(e){
// select the item that opened the submenu
let selected_item = $('.context-menu-active .context-menu-item-active-blurred').get(0);
$(selected_item).removeClass('context-menu-item-active-blurred');
$(selected_item).removeClass('has-open-context-menu-submenu');
$(selected_item).addClass('context-menu-item-active');
return false;
@ -191,7 +192,7 @@ $(document).bind('keydown', async function(e){
// if enter is pressed, trigger a click event on the selected item
else if($('.context-menu-active .context-menu-item-active').length > 0 && (e.which === 13)){
let selected_item = $('.context-menu-active .context-menu-item-active').get(0);
$(selected_item).trigger('click');
$(selected_item).trigger('click', {keyboard: true});
return false;
}
}
@ -482,10 +483,10 @@ $(document).bind('keydown', async function(e){
}
// search for matches
let haystack = $('.context-menu-active').find(`.context-menu-item`);
let haystack = $('.context-menu-active').find(`.context-menu-item > .contextmenu-label`);
for(let j=0; j < haystack.length; j++){
if($(haystack[j]).text().toLowerCase().startsWith(window.keypress_item_seach_term)){
matches.push(haystack[j])
matches.push(haystack[j].closest('.context-menu-item'));
}
}
@ -640,15 +641,11 @@ $(document).bind("keyup keydown", async function(e){
// if this is a selected context menu item, open it
// ---------------------------------------------
else if($('.context-menu-active .context-menu-item-active').length > 0 && (e.which === 13)){
// let selected_item = $('.context-menu-active .context-menu-item-active').get(0);
// $(selected_item).trigger('mouseover');
// $(selected_item).trigger('click');
let selected_item = $('.context-menu-active .context-menu-item-active').get(0);
$(selected_item).removeClass('context-menu-item-active');
$(selected_item).addClass('context-menu-item-active-blurred');
$(selected_item).trigger('mouseover');
$(selected_item).trigger('click');
$(selected_item).trigger('mouseover', {keyboard: true});
$(selected_item).trigger('click', {keyboard: true});
if($('.context-menu[data-is-submenu="true"]').length > 0){
let selected_item = $('.context-menu[data-is-submenu="true"] .context-menu-item').get(0);
window.select_ctxmenu_item(selected_item);