Распространение события "вверх"
В поисках вёрстки собственного меню чисто на 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, время: 09:29. |