Skip to content

Commit

Permalink
jsdialog: open submenu on hover in dropdowns
Browse files Browse the repository at this point in the history
- showsubmenu event on hover
- hidedropdown event on leave
- submenu is inserted into the same overlay as parent dropdown
- don't destory overlay if submenu is closed, do that only for root
- works on tablet / touch device

Signed-off-by: Szymon Kłos <[email protected]>
Change-Id: Ibb4a747555e172dd4e040950cdfd309560f214a7
  • Loading branch information
eszkadev committed Oct 31, 2023
1 parent d87c718 commit 56327b8
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 19 deletions.
5 changes: 5 additions & 0 deletions browser/css/jsdialogs.css
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,11 @@ input[type='number']:hover::-webkit-outer-spin-button {
border-radius: var(--border-radius);
}

.modalpopup[id$='-dropdown'] {
/* submenu is inserted into the same overlay, dont make it relative to parent */
position: absolute !important;
}

.modalpopup[id$='-dropdown'] .ui-dialog-content {
padding: 0px;
}
Expand Down
16 changes: 14 additions & 2 deletions browser/src/control/Control.JSDialog.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ L.Control.JSDialog = L.Control.extend({

L.DomUtil.remove(this.dialogs[id].container);

if (this.dialogs[id].overlay)
if (this.dialogs[id].overlay && !this.dialogs[id].isSubmenu)
L.DomUtil.remove(this.dialogs[id].overlay);

delete this.dialogs[id];
Expand All @@ -71,7 +71,7 @@ L.Control.JSDialog = L.Control.extend({

close: function(id, sendCloseEvent) {
if (id && this.dialogs[id]) {
if (!sendCloseEvent && this.dialogs[id].overlay)
if (!sendCloseEvent && this.dialogs[id].overlay && !this.dialogs[id].isSubmenu)
L.DomUtil.remove(this.dialogs[id].overlay);

if (this.dialogs[id].timeoutId)
Expand Down Expand Up @@ -201,6 +201,12 @@ L.Control.JSDialog = L.Control.extend({
},

getOrCreateOverlay: function(instance) {
// Submenu is created inside the same overlay as parent dropdown
if (instance.isDropdown && instance.isSubmenu) {
instance.overlay = document.body.querySelector('.jsdialog-overlay');
return;
}

// Dialogue overlay which will allow automatic positioning and cancellation of the dialogue if cancellable.
var overlay = L.DomUtil.get(instance.id + '-overlay');
if (!overlay) {
Expand Down Expand Up @@ -379,6 +385,12 @@ L.Control.JSDialog = L.Control.extend({
else
console.error('cannot get focus for widget: "' + instance.init_focus_id + '"');
}

if (instance.isDropdown && instance.isSubmenu) {
instance.container.addEventListener('mouseleave', function () {
instance.builder.callback('combobox', 'hidedropdown', {id: instance.id}, null, instance.builder);
});
}
},

setPosition: function(instance, updatedPos) {
Expand Down
22 changes: 10 additions & 12 deletions browser/src/control/Control.NotebookbarBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -842,19 +842,17 @@ L.Control.NotebookbarBuilder = L.Control.JSDialogBuilder.extend({
var dropdownId = data.id;
var clickFunction = function () {
var callback = function(objectType, eventType, object, data, entry) {
if (eventType === 'selected') {
if ((eventType === 'selected' || eventType === 'showsubmenu') && entry.id) {
var pos = data.substr(0, parseInt(data.indexOf(';')));
if (entry.id) {
var subDropdownId = dropdownId + '-' + pos;
var dropdown = JSDialog.GetDropdown(subDropdownId);
var container = dropdown.querySelector('.ui-grid');
container.innerHTML = getMenuHtml(entry.id);
JSDialog.MakeFocusCycle(container);
JSDialog.GetFocusableElements(container)[0].focus();
} else if (entry.uno) {
builder.map.sendUnoCommand(entry.uno);
JSDialog.CloseDropdown(dropdownId);
}
var subDropdownId = dropdownId + '-' + pos;
var dropdown = JSDialog.GetDropdown(subDropdownId);
var container = dropdown.querySelector('.ui-grid');
container.innerHTML = getMenuHtml(entry.id);
JSDialog.MakeFocusCycle(container);
JSDialog.GetFocusableElements(container)[0].focus();
} else if (eventType === 'selected' && entry.uno) {
builder.map.sendUnoCommand(entry.uno);
JSDialog.CloseDropdown(dropdownId);
}

return true;
Expand Down
22 changes: 18 additions & 4 deletions browser/src/control/jsdialog/Util.Dropdown.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,12 @@ function _createDropdownId(id) {
return id + '-dropdown';
}

JSDialog.OpenDropdown = function (id, popupParent, entries, innerCallback, popupAnchor) {
JSDialog.OpenDropdown = function (id, popupParent, entries, innerCallback, popupAnchor, isSubmenu) {
var dropdownWindowId = _createDropdownId(id);
var json = {
id: dropdownWindowId,
type: 'dropdown',
isSubmenu: isSubmenu,
jsontype: 'dialog',
popupParent: popupParent,
popupAnchor: popupAnchor,
Expand Down Expand Up @@ -58,17 +59,30 @@ JSDialog.OpenDropdown = function (id, popupParent, entries, innerCallback, popup
json.children[0].children.push(entry);
}

var lastSubMenuOpened = null;
var generateCallback = function (targetEntries) {
return function(objectType, eventType, object, data) {
if (eventType === 'selected') {
if (eventType === 'selected' || eventType === 'showsubmenu') {
var pos = parseInt(data.substr(0, data.indexOf(';')));
if (targetEntries[pos].items) {
if (lastSubMenuOpened) {
var submenu = JSDialog.GetDropdown(lastSubMenuOpened);
if (submenu) {
JSDialog.CloseDropdown(lastSubMenuOpened);
lastSubMenuOpened = null;
}
}

// open submenu
var dropdown = JSDialog.GetDropdown(object.id);
var subMenuId = object.id + '-' + pos;
var targetEntry = dropdown.querySelectorAll('.ui-grid-cell')[pos + 1];
JSDialog.OpenDropdown(object.id + '-' + pos, targetEntry, targetEntries[pos].items,
generateCallback(targetEntries[pos].items), 'top-end');
JSDialog.OpenDropdown(subMenuId, targetEntry, targetEntries[pos].items,
generateCallback(targetEntries[pos].items), 'top-end', true);
lastSubMenuOpened = subMenuId;
}
} else if (!lastSubMenuOpened && eventType === 'hidedropdown') {
JSDialog.CloseDropdown(id);
}

// for multi-level menus last parameter should be used to handle event (it contains selected entry)
Expand Down
10 changes: 9 additions & 1 deletion browser/src/control/jsdialog/Widget.Combobox.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,10 @@ JSDialog.comboboxEntry = function (parentContainer, data, builder) {
}
}

var entryData = data.pos + ';' + data.text;

var clickFunction = function () {
builder.callback('combobox', 'selected', {id: data.comboboxId}, data.pos + ';' + data.text, builder);
builder.callback('combobox', 'selected', {id: data.comboboxId}, entryData, builder);
};

entry.addEventListener('click', clickFunction);
Expand All @@ -80,6 +82,12 @@ JSDialog.comboboxEntry = function (parentContainer, data, builder) {
}
});

if (data.hasSubMenu) {
entry.addEventListener('mouseover', function () {
builder.callback('combobox', 'showsubmenu', {id: data.comboboxId}, entryData, builder);
});
}

return false;
};

Expand Down

0 comments on commit 56327b8

Please sign in to comment.