Распространение события "вверх"
В поисках вёрстки собственного меню чисто на CSS с использованием "радиокнопок", наткнулся на ситуацию, что всё вроде бы работает как и хотелось, но ключевое событие не срабатывает.
А именно, ключевой чекбокс, который управляет "выпаданием" подменю, почему-то при удержании ЛКМ реагирует, но на клик по пункту меню, когда все подменю должны скрыться, не работает.
<html>
<head>
<style>
menu {
display :inline-block;
list-style-type :none;
margin :0;
padding :0;
}
input[type=checkbox] ~ menu li {
display :inline-block;
vertical-align :top;
}
input[type=checkbox] ~ menu li menu {
display :none;
}
input[type=checkbox]:checked ~ menu li input:checked + menu {
display :block;
}
input[type=checkbox] ~ menu li menu li:first-child {
border-top :thick outset grey;
}
input[type=checkbox] ~ menu li menu li:last-child {
border-bottom :thick outset grey;
}
input[type=checkbox] ~ menu li menu li input {
border-left :thick outset grey;
border-right :thick outset grey;
}
input[type=checkbox] ~ menu li menu li input:hover {
border-left :thick outset grey;
border-right :thick outset grey;
background-color:red;
}
input[type=checkbox]:checked ~ menu li menu li input:hover,
input[type=checkbox]:checked ~ menu li menu li input:checked {
border-left :thick inset grey;
border-right :thick inset grey;
background-color:red;
}
input[type=checkbox] ~ menu li input {
border-top :thin outset transparent;
border-bottom :thin outset transparent;
border-left :thin outset transparent;
border-right :thin outset transparent;
margin :0;
padding :0;
appearance :none;
}
input[type=checkbox] ~ menu li input:hover {
border-top :thin outset grey;
border-bottom :thin outset grey;
border-left :thin outset grey;
border-right :thin outset grey;
}
input[type=checkbox]:checked ~ menu li input:checked {
border-top :thin inset grey;
border-bottom :thin inset grey;
border-left :thin inset grey;
border-right :thin inset grey;
}
input[type=checkbox] ~ menu li menu {
background-color:yellow;
display :none;
position :absolute;
}
input[type=checkbox] ~ menu li input:checked + menu {
background-color:red;
}
input[type=checkbox] ~ menu li menu li {
display :block;
}
input[type=checkbox] ~ menu li menu li hr {
border-top :thin inset grey;
border-bottom :thin inset grey;
border-left :thick outset grey;
border-right :thick outset grey;
width :calc(100% - thick);
margin :0;
}
input[type=checkbox] ~ menu li menu li input {
background-color:pink;
display :block;
width :calc(100%);
padding-right :1em;
}
input[type=checkbox] ~ menu li menu li:not([title]) menu {
background-color:green;
display :none;
left :100%;
}
input[type=checkbox] ~ menu li menu li:not([title]) input:checked + menu {
background-color:blue;
display :inline-block;
position :absolute;
top :calc(100% - 2em);
left :calc(100% + 0em);
}
input[type=checkbox] ~ menu li menu li:not([title]) input::after {
position :absolute;
right :0.5em;
color :yellow;
content :"\25B6";
visibility :visible;
}
input[type=checkbox] ~ menu li menu li[title] input::after {
visibility :hidden;
}
input[type=checkbox] ~ menu li menu li input:checked::after {
color :blue;
}
input[type=checkbox] ~ menu li menu li input + menu {
background-color:green;
display :none;
margin :0;
padding :0;
}
input[type=checkbox] ~ menu li menu li input:checked {
border-left :thick inset grey;
border-right :thick inset grey;
background-color:yellow;
}
input[type=radio]::before {
content :attr(value) attr(top);
}
</style>
</head>
<body>
<label for=MenuBar>
<!-- нормально, вне отладки - style=display:none -->
<input type=checkbox autocheck id=MenuBar checked style=display:inline />
<menu>
<li title='File'>
<input type=radio name=mnu1 value='File' />
<menu>
<li title='New'><input type=radio name=mnu2 value='New' onclick='alert(this.value)' /></li>
<li><hr /></li>
<li title='Exit'><input type=radio name=mnu2 value='Exit' onclick='alert(this.value)' /></li>
</menu>
</li>
<li title='Edit'>
<input type=radio name=mnu1 value='Edit' />
<menu>
<li title='Undo'><input type=radio name=mnu2 value='Undo' onclick='alert(this.value)' /></li>
<li title='Cut'><input type=radio name=mnu2 value='Cut' onclick='alert(this.value)' /></li>
<li title='Copy'><input type=radio name=mnu2 value='Copy' onclick='alert(this.value)' /></li>
<li title='Paste'><input type=radio name=mnu2 value='Paste' onclick='alert(this.value)' /></li>
<li>
<input type=radio name=mnu2 value='Paste...' />
<menu>
<li title='From clipboard'><input type=radio name=mnu3 value='From clipboard' onclick='alert(this.value)' /></li>
<li title='From file'><input type=radio name=mnu3 value='From file' onclick='alert(this.value)' /></li>
</menu>
</li>
<li title='Select all'><input type=radio name=mnu2 value='Select all' onclick='alert(this.value)' /></li>
</menu>
</li>
</menu>
</label>
<script>
document
.querySelectorAll("input[type=radio]")
.forEach(function(el) {
el.addEventListener("mouseover", function() { this.checked = true; });
*!*
el.addEventListener("click", () => document.getElementById("MenuBar").click());
*/!*
});
</script>
</body>
Если удалить явный обработчик события (строка №194) - перестаёт работать как надо.Иначе говоря, меньше JavaScript'а, больше CSS-описания. Готовые варианты с кучей избыточных элементов - не подходят: Хочется простенькое древо меню.:yes: |
У вас alert нем дает закрываться меню. Он создает модальное окно, которое не дает коду выполняться дальше, пока его не закрыть.
Замените alert на что нибудь другое, например на console.log и все нормально работает. Но есть другая проблема - меню не закрывается, если пользователь передумал. Кликнул по Edit, подменю отрылось. А дальше он не хочет ничего выбирать. Как закрыть его? Клик в пустое пространство не работает. |
Цитата:
(Даже показательно: Если по клику меню не закрылось, значит пошёл некий процесс.) Проблема в другом: Даже при отсутствии onclick-обработчика меню не закрывается!
<html>
<head>
<style>
menu {
display :inline-block;
list-style-type :none;
margin :0;
padding :0;
}
input[type=checkbox] ~ menu li {
display :inline-block;
vertical-align :top;
}
input[type=checkbox] ~ menu li menu {
display :none;
}
input[type=checkbox]:checked ~ menu li input:checked + menu {
display :block;
}
input[type=checkbox] ~ menu li menu li:first-child {
border-top :thick outset grey;
}
input[type=checkbox] ~ menu li menu li:last-child {
border-bottom :thick outset grey;
}
input[type=checkbox] ~ menu li menu li input {
border-left :thick outset grey;
border-right :thick outset grey;
}
input[type=checkbox] ~ menu li menu li input:hover {
border-left :thick outset grey;
border-right :thick outset grey;
background-color:red;
}
input[type=checkbox]:checked ~ menu li menu li input:hover,
input[type=checkbox]:checked ~ menu li menu li input:checked {
border-left :thick inset grey;
border-right :thick inset grey;
background-color:red;
}
input[type=checkbox] ~ menu li input {
border-top :thin outset transparent;
border-bottom :thin outset transparent;
border-left :thin outset transparent;
border-right :thin outset transparent;
margin :0;
padding :0;
appearance :none;
}
input[type=checkbox] ~ menu li input:hover {
border-top :thin outset grey;
border-bottom :thin outset grey;
border-left :thin outset grey;
border-right :thin outset grey;
}
input[type=checkbox]:checked ~ menu li input:checked {
border-top :thin inset grey;
border-bottom :thin inset grey;
border-left :thin inset grey;
border-right :thin inset grey;
}
input[type=checkbox] ~ menu li menu {
background-color:yellow;
display :none;
position :absolute;
}
input[type=checkbox] ~ menu li input:checked + menu {
background-color:red;
}
input[type=checkbox] ~ menu li menu li {
display :block;
}
input[type=checkbox] ~ menu li menu li hr {
border-top :thin inset grey;
border-bottom :thin inset grey;
border-left :thick outset grey;
border-right :thick outset grey;
width :calc(100% - thick);
margin :0;
}
input[type=checkbox] ~ menu li menu li input {
background-color:pink;
display :block;
width :calc(100%);
padding-right :1em;
}
input[type=checkbox] ~ menu li menu li:not([title]) menu {
background-color:green;
display :none;
left :100%;
}
input[type=checkbox] ~ menu li menu li:not([title]) input:checked + menu {
background-color:blue;
display :inline-block;
position :absolute;
top :calc(100% - 2em);
left :calc(100% + 0em);
}
input[type=checkbox] ~ menu li menu li:not([title]) input::after {
position :absolute;
right :0.5em;
color :yellow;
content :"\25B6";
visibility :visible;
}
input[type=checkbox] ~ menu li menu li[title] input::after {
visibility :hidden;
}
input[type=checkbox] ~ menu li menu li input:checked::after {
color :blue;
}
input[type=checkbox] ~ menu li menu li input + menu {
background-color:green;
display :none;
margin :0;
padding :0;
}
input[type=checkbox] ~ menu li menu li input:checked {
border-left :thick inset grey;
border-right :thick inset grey;
background-color:yellow;
}
input[type=radio]::before {
content :attr(value) attr(top);
}
</style>
</head>
<body>
<label for=MenuBar>
<input type=checkbox autocheck id=MenuBar checked style=display:inline />
<menu>
<li title='File'>
<input type=radio name=mnu1 value='File' />
<menu>
<li title='New'><input type=radio name=mnu2 value='New' /></li>
<li><hr /></li>
<li title='Exit'><input type=radio name=mnu2 value='Exit' /></li>
</menu>
</li>
<li title='Edit'>
<input type=radio name=mnu1 value='Edit' />
<menu>
<li title='Undo'><input type=radio name=mnu2 value='Undo' /></li>
<li title='Cut'><input type=radio name=mnu2 value='Cut' /></li>
<li title='Copy'><input type=radio name=mnu2 value='Copy' /></li>
<li title='Paste'><input type=radio name=mnu2 value='Paste' /></li>
<li>
<input type=radio name=mnu2 value='Paste...' />
<menu>
<li title='From clipboard'><input type=radio name=mnu3 value='From clipboard' onclick='console.log(this.value)' /></li>
<li title='From file'><input type=radio name=mnu3 value='From file' onclick='console.log(this.value)' /></li>
</menu>
</li>
<li title='Select all'><input type=radio name=mnu2 value='Select all' onclick='console.log(this.value)' /></li>
</menu>
</li>
</menu>
</label>
<script>
document
.querySelectorAll("input[type=radio]")
.forEach(function(el) {
el.addEventListener("mouseover", function() { this.checked = true; });
// el.addEventListener("click", () => document.getElementById("MenuBar").click());
});
</script>
</body>
Цитата:
Цитата:
Вешать на body событие onclick - меню вообще перестаёт открываться.:-? P.S.: Предыдущий вариант со скрытыми input-radio, но на a-href - работал. Решил вот полностью переработать свой, так сказать, "концепт": Поудалял все "якоря". |
Цитата:
|
Цитата:
В частности, разрабатывая утилиту под ПК (не под планшеты/смартфоны), пытаюсь стилизовать всё под "привычный старый интерфейс".;) Вообще-то, во всех готовых пакетах, в частности, лично мне не нравится избыточное описание под каждый тэг, так как привык пользоваться обычным Блокнотом без подсветки синтаксиса. Лучше наработать и отладить один раз сложный CSS, чем всякий раз десятки раз подписывать элементам явные стили. К примеру, тэг menu - и так всё там очевидно: Всё нужно отобразить как стандартное меню. Вот от этого и отталкиваюсь. Тогда как подобное меню слишком трудно воспринимается при редактировании страницы:
<html>
<head>
<link rel="stylesheet" href="https://unpkg.com/7.css">
</head>
<body>
<ul role="menubar" class="can-hover">
<li role="menuitem" tabindex="0" aria-haspopup="true">
File
<ul role="menu">
<li role="menuitem">
<a href="#menubar">
Open <span>Ctrl+O</span>
</a>
</li>
<li role="menuitem">
<a href="#menubar">
Save <span>Ctrl+S</span>
</a>
</li>
<li role="menuitem" class="has-divider">
<a href="#menubar">
Save As... <span>Ctrl+Shift+S</span>
</a>
</li>
<li role="menuitem"><a href="#menubar">Exit</a></li>
</ul>
</li>
<li role="menuitem" tabindex="0" aria-haspopup="true">
Edit
<ul role="menu">
<li role="menuitem"><a href="#menubar">Undo</a></li>
<li role="menuitem"><a href="#menubar">Copy</a></li>
<li role="menuitem"><a href="#menubar">Cut</a></li>
<li role="menuitem" class="has-divider"><a href="#menubar">Paste</a></li>
<li role="menuitem"><a href="#menubar">Delete</a></li>
<li role="menuitem"><a href="#menubar">Find...</a></li>
<li role="menuitem"><a href="#menubar">Replace...</a></li>
<li role="menuitem"><a href="#menubar">Go to...</a></li>
</ul>
</li>
<li role="menuitem" tabindex="0" aria-haspopup="true">
View
<ul role="menu">
<li role="menuitem" tabindex="0" aria-haspopup="true">
Zoom
<ul role="menu">
<li role="menuitem"><button>Zoom In</button></li>
<li role="menuitem"><button>Zoom Out</button></li>
</ul>
</li>
<li role="menuitem"><a href="#menubar">Status Bar</a></li>
</ul>
</li>
<li role="menuitem" tabindex="0" aria-haspopup="true">
Help
<ul role="menu">
<li role="menuitem"><a href="#menubar">View Help</a></li>
<li role="menuitem"><a href="#menubar">About</a></li>
</ul>
</li>
</ul>
</body>
Тем более, работает не совсем так, как в Windows'95. Что для меня принципиально важно.:victory:(Если не забыли: Во всех Windows меню открывается не наведением указателя, а кликом. И скрывается только по любому клику.) Конкретно мой вариант так и работает, но пока ещё глючит и без JavaScript-вкраплений никак не получается обходиться. (А хотелось бы.) Спасибо!:thanks: |
| Часовой пояс GMT +3, время: 21:57. |