tool-bar
tool-bar copied to clipboard
ToolBarDropdownMenu
Adding a dropdown menu that each option is a ToolBarButton.
It should be built on top of ToolBarItem.
We should use atom-select-list if possible.
References: https://www.w3schools.com/howto/howto_js_dropdown.asp Electron References if applicable: https://github.com/electron/electron/blob/v5.0.13/docs/api/menu-item.md https://github.com/electron/electron/blob/v5.0.13/docs/api/menu.md https://livebook.manning.com/book/electron-in-action/chapter-7/1
I wrote this but I cannot make it show the list
const {ToolBarButtonView} = require("./tool-bar-button-view");
const SelectListView = require('atom-select-list');
class ToolBarDropdown {
constructor (buttonOptions, listItems, group) {
this.element = document.createElement('div');
let dropdownButton = new ToolBarButtonView(buttonOptions, group);
this.element.appendChild(dropdownButton.element);
let list = document.createElement('div');
list.classList.add('dropdown-content');
let option = document.createElement('a');
this.dropdownList = list.appendChild(option);
this.element.appendChild(this.dropdownList);
// or dropdownButton.element
this.element.addEventListener('click', function (e) {
option.style.display = "block";
if (e.preventDefault) {
e.preventDefault();
e.stopPropagation();
}
});
}
}
inside toolbar.js:
const { ToolBarDropdown } = require('./items/tool-bar-dropdown');
exports.activate = function () {
toolBarView = new ToolBarView();
touchBarManager = new TouchBarManager();
// test dropdown
let toolBarManager = new ToolBarManager("Amin", toolBarView, touchBarManager);
let mydropdown = new ToolBarDropdown({
text: "hey",
callback: () => console.log("a")
},["option1", "option2"],"Amin");
console.log(mydropdown.element);
toolBarManager.addItem({element: mydropdown.element, priority: -1});
};
Maybe the callback executor of the button conflicts with the dropdown show.
I got it working using atom-select-list:
It isn't the most beautiful dropdown yet. Unfortunately, it changes the width of the toolbar itself.
The code
items/tool-bar-dropdown.js
const {ToolBarButtonView} = require("./tool-bar-button-view");
const SelectListView = require('atom-select-list');
class ToolBarDropdown {
constructor (buttonOptions, listItems, group) {
this.element = document.createElement('div');
buttonOptions.callback = () => {
if (mydropdown.list.selectList.element.hidden == true) {
mydropdown.list.show();
} else {
mydropdown.list.selectList.element.hidden = true;
}
}
this.button = new ToolBarButtonView(buttonOptions, group);
this.element.appendChild(this.button.element);
this.list= new DropdownSelector(listItems);
this.element.appendChild(this.list.selectList.element);
}
}
class DropdownSelector {
// Make a selector object (should be called once)
constructor(SelectorItems) {
// Defining a SelectListView with methods - https://github.com/atom/atom-select-list
this.selectList = new SelectListView({
// an array containing the objects you want to show in the select list
items: SelectorItems,
// // called whenever an item needs to be displayed.
elementForItem: (item) => {
const element = document.createElement("li");
element.textContent = item.text;
return element;
},
// // called to retrieve a string property on each item and that will be used to filter them.
filterKeyForItem: (item) => {
return item.text;
},
// // called when the user clicks or presses Enter on an item. // use `=>` for `this`
didConfirmSelection: (item) => {
item.callback();
this.selectList.element.hidden = true;
},
// // called when the user presses Esc or the list loses focus. // use `=>` for `this`
didCancelSelection: () => {
this.selectList.element.hidden = true;
},
});
this.selectList.element.style.position = "relative";
this.selectList.element.style.left = "20px";
// initially hidden
this.list.selectList.element.hidden = true;
}
// Show a selector object
show() {
// Show selector
this.selectList.element.hidden = false;
this.selectList.reset();
this.selectList.focus();
}
// Dispose selector
dispose() {
this.selectList.element.hidden = true;
this.selectList.destroy();
}
}
module.exports.ToolBarDropdown = ToolBarDropdown;
tool-bar.js activate function:
const { ToolBarDropdown } = require('./items/tool-bar-dropdown');
exports.activate = function () {
toolBarView = new ToolBarView();
touchBarManager = new TouchBarManager();
// test dropdown
let mygroup = "Amin";
let toolBarManager = new ToolBarManager(mygroup, toolBarView, touchBarManager);
let items = [
{text: "option1", callback: () => console.log("option1") },
{text: "option1", callback: () => console.log("option2") }
];
let mydropdown = new ToolBarDropdown({ icon: "star"}, items, mygroup);
toolBarManager.addItem({element: mydropdown.element, priority: -1});
};
It is more beautiful now using the actual button type of the Toolbar itself (without atom-select-list).
Still has the toolbar width changing issue:
The code
items/tool-bar-dropdown.js
const {ToolBarButtonView} = require("./tool-bar-button-view");
class ToolBarDropdown {
/**
*
* @param {ButtonOptions} titleOptions
* @param {ButtonOptions[]} listOptions
* @param {string} group
*/
constructor (titleOptions, listOptions, group) {
this.element = document.createElement('div');
this.createList(listOptions, group);
this.createTitle(titleOptions, group);
this.element.appendChild(this.title.element);
this.element.appendChild(this.listElement);
}
/**
*
* @param {ButtonOptions} titleOptions
* @param {string} group
*/
createTitle (titleOptions, group) {
// callback for titleButton
titleOptions.callback = () => {
if (this.isListHidden()) {
this.showList();
} else {
// to close the list when clicked again
this.hideList();
}
};
// create the title button
this.title = new ToolBarButtonView(titleOptions, group);
}
/**
*
* @param {ButtonOptions[]} listOptions
* @param {string} group
*/
createList(listOptions, group) {
// list container
this.listElement = document.createElement('div');
// creating each list button and appending it to the list container
for (let i =0, l = listOptions.length; i < l; i++) {
this.listElement.appendChild((new ToolBarButtonView(listOptions[i], group)).element);
}
this.listElement.style.position = "relative";
this.listElement.style.left = "20px";
// this.listElement.style.cssFloat = "right";
// initially hidden
this.hideList();
}
isListHidden() {
return this.listElement.hidden;
}
hideList() {
this.listElement.hidden = true;
}
showList() {
this.listElement.hidden = false;
}
}
module.exports.ToolBarDropdown = ToolBarDropdown;
tool-bar.js inside activate:
const { ToolBarDropdown } = require('./items/tool-bar-dropdown');
exports.activate = function () {
toolBarView = new ToolBarView();
touchBarManager = new TouchBarManager();
// test dropdown
let mygroup = "Amin";
let toolBarManager = new ToolBarManager(mygroup, toolBarView, touchBarManager);
let listOptions = [
{text: "option1", callback: () => console.log("option1") },
{text: "option2", callback: () => console.log("option2") }
];
let titleOption = {
icon: "star"
};
let mydropdown = new ToolBarDropdown(titleOption,listOptions, mygroup);
toolBarManager.addItem({element: mydropdown.element, priority: -1});
};
@suda @ericcornelissen any solution for the tool-bar width changing issue? I cannot make the dropdown be a float thing separate from the tool-bar width.
Don't really have the time to look into this right now, but the w3c solutions seems pretty nice to me.
Why doesn't the dropdown overlay whatever is below it? In fact, what is below it might not even be a toolbar, depending on the end-user setup.
I think we need to add a floating dropdown and position it under the actual button and not appendChild it to the tool-bar.
Not sure what you're trying to say @aminya :thinking:
I agree that it should be "floating" (though I don't think using CSS float
is the solution) and position under1 the actual button. However, your current solution looks (didn't test it) like it won't work if there is no toolbar below the button (e.g. when toolbar position is top) without expanding the toolbar.
Regarding appendChild
. This would depend on your implementation. Where do you plan to append it to? In the w3c solution it is inside a <div>
after the <button>
.
- However, if the toolbar is position at the bottom this doesn't work. Similarly, when it is position left or right, this might not work for buttons near the bottom.
I found this video. It is maybe related. https://www.youtube.com/watch?v=IF6k0uZuypA&t=619s
There are other ones too: https://www.youtube.com/results?search_query=dropdown+menu