Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый Вчера, 15:23
Аватар для Alikberov
Кандидат Javascript-наук
Отправить личное сообщение для Alikberov Посмотреть профиль Найти все сообщения от Alikberov
 
Регистрация: 16.08.2018
Сообщений: 112

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

Готовые варианты с кучей избыточных элементов - не подходят: Хочется простенькое древо меню.

Последний раз редактировалось Alikberov, Вчера в 15:54.
Ответить с цитированием
  #2 (permalink)  
Старый Вчера, 16:21
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,753

У вас alert нем дает закрываться меню. Он создает модальное окно, которое не дает коду выполняться дальше, пока его не закрыть.
Замените alert на что нибудь другое, например на console.log и все нормально работает.
Но есть другая проблема - меню не закрывается, если пользователь передумал. Кликнул по Edit, подменю отрылось. А дальше он не хочет ничего выбирать. Как закрыть его? Клик в пустое пространство не работает.
Ответить с цитированием
  #3 (permalink)  
Старый Вчера, 16:57
Аватар для Alikberov
Кандидат Javascript-наук
Отправить личное сообщение для Alikberov Посмотреть профиль Найти все сообщения от Alikberov
 
Регистрация: 16.08.2018
Сообщений: 112

Сообщение от voraa Посмотреть сообщение
У вас alert нем дает закрываться меню. Он создает модальное окно, которое не дает коду выполняться дальше, пока его не закрыть.
Замените alert на что нибудь другое, например на console.log и все нормально работает.
У меня меню закрывается после нажатия кнопки в Alert'е. Это - не принципиально.
(Даже показательно: Если по клику меню не закрылось, значит пошёл некий процесс.)

Проблема в другом: Даже при отсутствии 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>

Цитата:
Но есть другая проблема - меню не закрывается, если пользователь передумал. Кликнул по Edit, подменю отрылось. А дальше он не хочет ничего выбирать. Как закрыть его?
Вторым нажатием на Edit (вариант в начале так и работает).
Цитата:
Клик в пустое пространство не работает.
Да, вот это - второй момент. Как тут быть?
Вешать на body событие onclick - меню вообще перестаёт открываться.

P.S.: Предыдущий вариант со скрытыми input-radio, но на a-href - работал.
Решил вот полностью переработать свой, так сказать, "концепт": Поудалял все "якоря".

Последний раз редактировалось Alikberov, Вчера в 17:14.
Ответить с цитированием
  #4 (permalink)  
Старый Вчера, 19:21
Аватар для voraa
Профессор
Отправить личное сообщение для voraa Посмотреть профиль Найти все сообщения от voraa
 
Регистрация: 03.02.2020
Сообщений: 2,753

Сообщение от Alikberov
Вторым нажатием на Edit (вариант в начале так и работает).
Это уже не стандартный интерфейс. Как пользователь узнает, что надо делать так? Ведь он привык при работе с другими программами, где есть меню просто кликать мимо.
Ответить с цитированием
  #5 (permalink)  
Старый Вчера, 21:03
Аватар для Alikberov
Кандидат Javascript-наук
Отправить личное сообщение для Alikberov Посмотреть профиль Найти все сообщения от Alikberov
 
Регистрация: 16.08.2018
Сообщений: 112

Сообщение от voraa Посмотреть сообщение
Это уже не стандартный интерфейс. Как пользователь узнает, что надо делать так? Ведь он привык при работе с другими программами, где есть меню просто кликать мимо.
Есть готовые стили, где можно олдшкулно интерфейс свой отобразить (например, Меню Windows'7), но там меню несколько иначе работает.

В частности, разрабатывая утилиту под ПК (не под планшеты/смартфоны), пытаюсь стилизовать всё под "привычный старый интерфейс".

Вообще-то, во всех готовых пакетах, в частности, лично мне не нравится избыточное описание под каждый тэг, так как привык пользоваться обычным Блокнотом без подсветки синтаксиса.
Лучше наработать и отладить один раз сложный 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. Что для меня принципиально важно.
(Если не забыли: Во всех Windows меню открывается не наведением указателя, а кликом. И скрывается только по любому клику.)

Конкретно мой вариант так и работает, но пока ещё глючит и без JavaScript-вкраплений никак не получается обходиться.
(А хотелось бы.)

Спасибо!

Последний раз редактировалось Alikberov, Сегодня в 11:13.
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Слишком длинный код Сергей Ракипов Общие вопросы Javascript 14 25.07.2024 18:46
свойства объекта события Morr123 Элементы интерфейса 3 10.08.2016 06:36
Обработка события внутри события grifangel Общие вопросы Javascript 6 04.09.2014 12:34
Дебаг js, или как найти обработчик события для тега jimm88 Events/DOM/Window 1 18.04.2012 15:11
Передача параметров в колбэки и дальнейшее их вешанье на события. Gremlin Общие вопросы Javascript 17 13.08.2011 08:54