Skip to content

Commit a3848ff

Browse files
committed
Bug fixes, positioning updated, enabled option
1 parent 6ba3fc3 commit a3848ff

File tree

7 files changed

+190
-36
lines changed

7 files changed

+190
-36
lines changed

index.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
11
<!DOCTYPE html>
22
<html>
33
<head>
4-
<title></title>
54
<link rel=stylesheet type=text/css href=nwjs-menu-browser.css>
65
</head>
76
<body>
8-
<script src=index.js></script>
7+
<script src=app.js></script>
98
</body>
109
</html>

nwjs-menu-browser.css

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ html, body {
66

77
.contextmenu {
88
min-width: 100px;
9-
min-height: 150px;
109
background-color: #eee;
1110
position: fixed;
1211
opacity: 0;
@@ -21,6 +20,10 @@ html, body {
2120
font-size: 11pt;
2221
box-shadow: rgba(43, 43, 43, 0.34) 1px 1px 11px 0px;
2322
color: #222621;
23+
-webkit-touch-callout: none; /* iOS Safari */
24+
-webkit-user-select: none; /* Safari */
25+
user-select: none;
26+
/* width: 100%; */
2427
}
2528

2629
.contextmenu.show {
@@ -42,7 +45,9 @@ html, body {
4245
padding: 1px 0 2px;
4346
box-sizing: border-box;
4447
position: relative;
45-
display: flex;
48+
display: grid;
49+
grid-template-columns: 20px auto 20px;
50+
width: 100%;
4651
}
4752

4853
.menu-item.normal:hover,
@@ -52,8 +57,7 @@ html, body {
5257
}
5358

5459
.menu-item.normal > div {
55-
display: inline-flex;
56-
align-items: center;
60+
align-self: center;
5761
}
5862

5963
.menu-item.normal .icon {
@@ -78,4 +82,18 @@ li.menu-item.separator {
7882
box-sizing: border-box;
7983
padding: 0 3px 0 0;
8084
text-align: right;
85+
}
86+
87+
.label {
88+
padding: 0 20px 0 0;
89+
grid-column-start: 2;
90+
grid-column-end: 3;
91+
}
92+
93+
li.menu-item.normal.disabled {
94+
color: #ababab;
95+
}
96+
97+
li.menu-item.normal.disabled:hover {
98+
background-color: transparent;
8199
}

src-app/app.js

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
import { Menu, MenuItem } from 'nwjs-browser-menu';
2+
3+
let m = new Menu();
4+
m.append(new MenuItem({
5+
label: 'Log XMLHttpRequests'
6+
}));
7+
8+
m.append(new MenuItem({
9+
label: 'Log XMLHttpRequests'
10+
}));
11+
m.append(new MenuItem({
12+
label: 'Clear console'
13+
}));
14+
m.append(new MenuItem({
15+
label: 'Clear console history'
16+
}));
17+
m.append(new MenuItem({
18+
label: 'Save as...',
19+
enabled: false
20+
}));
21+
22+
let sm = new Menu();
23+
for(let i=10; i < 20; i++) {
24+
let mi = new MenuItem({
25+
label: 'Item ' + i,
26+
click: function() { //jshint ignore:line
27+
alert('hello m8 - ' + i);
28+
}
29+
});
30+
sm.append(mi);
31+
}
32+
33+
let mi = new MenuItem({
34+
label: 'Filter',
35+
submenu: sm
36+
});
37+
38+
m.insert(mi, 1);
39+
40+
let mi4 = new MenuItem({
41+
type: 'separator'
42+
});
43+
44+
m.insert(mi4, 2);
45+
46+
let sm2 = new Menu();
47+
for(let i=20; i < 30; i++) {
48+
let mi = new MenuItem({
49+
label: 'Item ' + i
50+
});
51+
sm2.append(mi);
52+
}
53+
54+
let mi2 = new MenuItem({
55+
label: 'Item with sub 2',
56+
submenu: sm2
57+
});
58+
59+
let mi3 = new MenuItem({
60+
type: 'separator'
61+
});
62+
63+
sm.insert(mi2, 1);
64+
sm.insert(mi3, 2);
65+
66+
console.log(m, sm, sm2);
67+
68+
document.addEventListener('contextmenu', (e) => {
69+
e.preventDefault();
70+
m.popup(e.clientX, e.clientY);
71+
return false;
72+
});
73+
74+
window.Menu = Menu;
75+
window.MenuItem = MenuItem;
76+
window.m = m;

src/index.js

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
module.exports = {
2-
Menu: require('./menu'),
3-
MenuItem: require('./menu-item')
1+
import Menu from './menu';
2+
import MenuItem from './menu-item';
3+
4+
export {
5+
Menu,
6+
MenuItem
47
};

src/is-decendant.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
module.exports = function isDescendant(parent, child) {
1+
export default function isDescendant(parent, child) {
22
let node = child.parentNode;
33
while(node !== null) {
4-
if(node == parent) {
4+
if(node === parent) {
55
return true;
66
}
77
node = node.parentNode;
88
}
99
return false;
10-
};
10+
}

src/menu-item/index.js

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const Menu = require('../menu');
2-
const isDescendant = require('../is-decendant');
1+
import Menu from '../menu';
2+
import isDescendant from '../is-decendant';
33

4-
module.exports = class MenuItem {
4+
class MenuItem {
55
constructor(settings = {}) {
66
const modifiersEnum = ['cmd', 'command', 'super', 'shift', 'ctrl', 'alt'];
77
const typeEnum = ['separator', 'checkbox', 'normal'];
@@ -14,6 +14,7 @@ module.exports = class MenuItem {
1414
submenu.parentMenuItem = this;
1515
}
1616

17+
1718
Object.defineProperty(this, 'type', {
1819
get: () => {
1920
return type;
@@ -64,7 +65,10 @@ module.exports = class MenuItem {
6465
this.iconIsTemplate = settings.iconIsTemplate || false;
6566
this.tooltip = settings.tooltip || '';
6667
this.checked = settings.checked || false;
67-
this.enabled = settings.enabled || true;
68+
69+
this.enabled = settings.enabled;
70+
if(typeof settings.enabled === 'undefined') this.enabled = true;
71+
6872
this.key = settings.key || null;
6973
this.node = null;
7074

@@ -89,14 +93,21 @@ module.exports = class MenuItem {
8993
}
9094
}
9195

96+
_clickHandle_click() {
97+
console.log(Boolean(this.submenu));
98+
99+
if(!this.enabled || this.submenu) return;
100+
this.parentMenu.popdownAll();
101+
if(this.click) this.click();
102+
}
103+
92104
buildItem() {
93105
let node = document.createElement('li');
94106
node.classList.add('menu-item', this.type);
95107

96-
node.addEventListener('click', () => {
97-
document.removeEventListener('click', this.parentMenu.clickHandler);
98-
this.parentMenu.popdown();
99-
if(this.click) this.click();
108+
node.addEventListener('click', this._clickHandle_click.bind(this));
109+
node.addEventListener('mouseup', (e) => {
110+
if(e.button === 2) this._clickHandle_click();
100111
});
101112

102113
let iconWrapNode = document.createElement('div');
@@ -121,14 +132,25 @@ module.exports = class MenuItem {
121132
modifierNode.textContent = '▶︎';
122133

123134
node.addEventListener('mouseout', (e) => {
124-
if(!isDescendant(node, e.target)) this.submenu.popdown();
125-
135+
if(node !== e.target) {
136+
if(!isDescendant(node, e.target)) this.submenu.popdown();
137+
}
126138
node.classList.add('submenu-active');
127139
});
128140
}
129141

130-
node.addEventListener('mouseover', () => {
142+
if(!this.enabled) {
143+
node.classList.add('disabled');
144+
}
145+
146+
node.addEventListener('mouseover', (e) => {
131147
if(this.submenu) {
148+
if(this.submenu.node) {
149+
if(this.submenu.node.classList.contains('show')) {
150+
return;
151+
}
152+
}
153+
132154
let parentNode = node.parentNode;
133155

134156
let x = parentNode.offsetWidth + parentNode.offsetLeft - 2;
@@ -151,4 +173,6 @@ module.exports = class MenuItem {
151173
this.node = node;
152174
return node;
153175
}
154-
};
176+
}
177+
178+
export default MenuItem;

src/menu/index.js

Lines changed: 46 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
const MenuItem = require('../menu');
2-
const isDescendant = require('../is-decendant');
1+
import MenuItem from '../menu-item';
2+
import isDescendant from '../is-decendant';
33

4-
module.exports = class Menu {
4+
class Menu {
55
constructor(settings = {}) {
66
const typeEnum = ['contextmenu', 'menubar'];
77
let items = [];
@@ -78,8 +78,9 @@ module.exports = class Menu {
7878
}
7979

8080
_clickHandle_hideMenu(e) {
81+
console.log('called', this.node, e.target);
8182
if(e.target !== this.node && !isDescendant(this.node, e.target)) {
82-
this.node.classList.remove('show');
83+
if(this.node.classList.contains('show')) this.popdown();
8384
}
8485
}
8586

@@ -89,7 +90,9 @@ module.exports = class Menu {
8990
}
9091

9192
popup(x, y, submenu = false) {
93+
console.log('popup called');
9294
let menuNode;
95+
let setRight = false;
9396

9497
if(this.node) {
9598
menuNode = this.node;
@@ -110,40 +113,61 @@ module.exports = class Menu {
110113
let height = menuNode.clientHeight;
111114

112115
if((x + width) > window.innerWidth) {
113-
x = window.innerWidth - width;
116+
setRight = true;
117+
if(submenu) {
118+
let node = this.parentMenu.node;
119+
x = node.offsetWidth + ((window.innerWidth - node.offsetLeft) - node.offsetWidth) - 2;
120+
} else {
121+
x = 0;
122+
}
114123
}
115124

116125
if((y + height) > window.innerHeight) {
117126
y = window.innerHeight - height;
118127
}
119128

120-
menuNode.style.left = x + 'px';
129+
if(!setRight) {
130+
menuNode.style.left = x + 'px';
131+
menuNode.style.right = 'auto';
132+
} else {
133+
menuNode.style.right = x + 'px';
134+
menuNode.style.left = 'auto';
135+
}
136+
121137
menuNode.style.top = y + 'px';
122138
menuNode.classList.add('show');
123139

124-
document.addEventListener('click', this.clickHandler);
140+
if(!submenu) document.addEventListener('click', this.clickHandler);
125141
}
126142

127143
popdown() {
128144
if(this.node) this.node.classList.remove('show');
145+
document.removeEventListener('click', this.clickHandler);
129146

130147
this.items.forEach(item => {
131148
if(item.submenu) {
132-
item.node.classList.remove('submenu-active');
133149
item.submenu.popdown();
134150
}
135151
});
136152
}
137153

154+
popdownAll() {
155+
let menu = this;
156+
while(menu.parentMenu) {
157+
if(menu.parentMenu) {
158+
menu = menu.parentMenu;
159+
}
160+
}
161+
162+
menu.popdown();
163+
}
164+
138165
buildMenu(submenu = false) {
139166
let menuNode = this.menuNode;
140167
if(submenu) menuNode.classList.add('submenu');
141168

142169
this.items.forEach(item => {
143170
let itemNode = item.buildItem();
144-
// if(item.submenu) {
145-
// let submenuNode = item.submenu.buildMenu(true);
146-
// }
147171
menuNode.appendChild(itemNode);
148172
});
149173

@@ -155,4 +179,14 @@ module.exports = class Menu {
155179
node.classList.add(this.type);
156180
return node;
157181
}
158-
};
182+
183+
get parentMenu() {
184+
if(this.parentMenuItem) {
185+
return this.parentMenuItem.parentMenu;
186+
} else {
187+
return undefined;
188+
}
189+
}
190+
}
191+
192+
export default Menu;

0 commit comments

Comments
 (0)