Управляйте: до и: после с помощью javascript

У меня есть раскрывающаяся панель навигации (скрипт здесь и фрагмент ниже). При щелчке по SubItem функция JS выполняет вызов Ajax (не показан). Чего я хочу добиться, так это скрыть список SubItems при щелчке по SubItem, чтобы избежать текущего раздражающего перекрытия.

function GetData(TheClicked,WhichItem) {
	//In the working version, here is an Ajax call;
	document.getElementById("MainContainer").innerHTML = 'SomeTextSomeTextSomeTextSomeText';
}
body {
	margin: 0;
	padding: 0;
	background: #fcf8f2;
}
.NavBarContainer {
	position: block;
  clear: both;
	top: 0;
	width: 100%;
	background: #4a535b;
}
.NavBar ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.NavBar ul li {
	display: block;
	position: relative;
	float: left;
}
.NavBar li ul { display: none; }

.NavBar ul li a {
	display: block;
	padding: 0.6rem;
	text-decoration: none;
	white-space: nowrap;
	color: #fffbf4;
	font-size:1.2rem;
	letter-spacing:0.1rem;
	-webkit-animation: fadeIn 1s;
	animation: fadeIn 1s;
}

.NavBar ul li a:hover { 
	background: #2c3e50; 
	-webkit-transition: background-color 0.5s ease-out;
	-moz-transition: background-color 0.5s ease-out;
	-o-transition: background-color 0.5s ease-out;
	transition: background-color 0.5s ease-out;
}
.NavBar li:hover > ul {
	display: block;
	position: absolute;
}

.NavBar li:hover li { float: none; }

.NavBar li:hover a { background: #4a535b; }

.NavBar li:hover li a:hover { background: #2c3e50; }

.NavBar li ul li { border-top: 0; }
.NavBar ul ul ul {
	left: 100%;
  top: 0;
}

.NavBar ul:before,
.NavBar ul:after {
	content: " "; /* 1 */
	display: table; /* 2 */
}
.NavBar ul:after { clear: both; }

.MainContainer {
	background: #fffcf9;
	margin: auto;
	width: 80%;
	border-style:solid;
	border-width:thin;
	border-color:#e2e0d9;
	padding:1rem;
  color: red;
}
<div class = "NavBarContainer" id = "NavBarContainer">
<div class = "NavBar">
  <ul>
    <li><a href = "#">Item#1</a>
      <ul>
        <li><a href = "#" onclick = "GetData(this,'SubItem_11');">SubItem_11</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_12'); return false;">SubItem_12</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_13'); return false;">SubItem_13</a></li>
      </ul>
    </li>
		<li><a href = "#">Item#2</a>
      <ul>
        <li><a href = "#" onclick = "GetData(this,'SubItem_21'); return false;">SubItem_21</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_22'); return false;">SubItem_22</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_23'); return false;">SubItem_23</a></li>
      </ul>   
		</li> 
		<li><a href = "#">Item#3</a>
      <ul>
        <li><a href = "#" onclick = "GetData(this,'SubItem_31');">SubItem_31</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_32');">SubItem_32</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_33');">SubItem_33</a></li>
      </ul>   
		</li>     
  </ul>     
</div>
</div>


<div class = "MainContainer" id = "MainContainer">...</div>

в чем именно проблема?:

Pointy 30.12.2018 17:18

Если вы, например, нажмете SubItem_22 и не отодвинете мышь, текст ответа будет ниже раскрывающегося списка. Я хочу, чтобы список SubItems исчезал при нажатии (и появлялся снова только при наведении курсора мыши на главное меню).

CMArg 30.12.2018 17:20

Псевдоклассы CSS делают то, что делают, и вы не можете повлиять на это с помощью JavaScript. Если вы хотите, чтобы ваше меню работало по-другому, вам придется делать это с помощью JavaScript, обрабатывая события «mouseenter», «mouseleave» и т. д. И добавляя / удаляя классы по мере необходимости.

Pointy 30.12.2018 17:29

Я понимаю. Я надеялся, что есть какой-то JS-трюк, чтобы не переписывать все существующие CSS. Большое спасибо.

CMArg 30.12.2018 17:35
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
4
84
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Что вы можете сделать, так это деактивировать события указателя и повторно активировать его сразу после того, как подменю скрыто, например:

function GetData(TheClicked,WhichItem) {
    //In the working version, here is an Ajax call;
    document.getElementById("MainContainer").innerHTML = 'SomeTextSomeTextSomeTextSomeText';
    // The parent ul
    var parent = TheClicked.parentElement.parentElement;
    // De-activate the pointer-events
    parent.style['pointer-events'] = 'none';
    // Re-activate the pointer-events after 100ms
    setTimeout(function() {
        parent.style['pointer-events'] = '';
    }, 100);
}
body {
	margin: 0;
	padding: 0;
	background: #fcf8f2;
}
.NavBarContainer {
	position: block;
  clear: both;
	top: 0;
	width: 100%;
	background: #4a535b;
}
.NavBar ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

.NavBar ul li {
	display: block;
	position: relative;
	float: left;
}
.NavBar li ul { display: none; }

.NavBar ul li a {
	display: block;
	padding: 0.6rem;
	text-decoration: none;
	white-space: nowrap;
	color: #fffbf4;
	font-size:1.2rem;
	letter-spacing:0.1rem;
	-webkit-animation: fadeIn 1s;
	animation: fadeIn 1s;
}

.NavBar ul li a:hover { 
	background: #2c3e50; 
	-webkit-transition: background-color 0.5s ease-out;
	-moz-transition: background-color 0.5s ease-out;
	-o-transition: background-color 0.5s ease-out;
	transition: background-color 0.5s ease-out;
}
.NavBar li:hover > ul {
	display: block;
	position: absolute;
}

.NavBar li:hover li { float: none; }

.NavBar li:hover a { background: #4a535b; }

.NavBar li:hover li a:hover { background: #2c3e50; }

.NavBar li ul li { border-top: 0; }
.NavBar ul ul ul {
	left: 100%;
  top: 0;
}

.NavBar ul:before,
.NavBar ul:after {
	content: " "; /* 1 */
	display: table; /* 2 */
}
.NavBar ul:after { clear: both; }

.MainContainer {
	background: #fffcf9;
	margin: auto;
	width: 80%;
	border-style:solid;
	border-width:thin;
	border-color:#e2e0d9;
	padding:1rem;
  color: red;
}
<div class = "NavBarContainer" id = "NavBarContainer">
<div class = "NavBar">
  <ul>
    <li><a href = "#">Item#1</a>
      <ul>
        <li><a href = "#" onclick = "GetData(this,'SubItem_11');">SubItem_11</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_12'); return false;">SubItem_12</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_13'); return false;">SubItem_13</a></li>
      </ul>
    </li>
		<li><a href = "#">Item#2</a>
      <ul>
        <li><a href = "#" onclick = "GetData(this,'SubItem_21'); return false;">SubItem_21</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_22'); return false;">SubItem_22</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_23'); return false;">SubItem_23</a></li>
      </ul>   
		</li> 
		<li><a href = "#">Item#3</a>
      <ul>
        <li><a href = "#" onclick = "GetData(this,'SubItem_31');">SubItem_31</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_32');">SubItem_32</a></li>
        <li><a href = "#" onclick = "GetData(this,'SubItem_33');">SubItem_33</a></li>
      </ul>   
		</li>     
  </ul>     
</div>
</div>


<div class = "MainContainer" id = "MainContainer">...</div>

Я пробовал оба решения (@arieljoud и @Armel), и оба выполняют свою работу, и оба мне нравятся. Один из вас вносит предложения, другой - фрагмент. Принятие того или иного (для меня) одинаково, поэтому решение было случайным. Грасиас!

CMArg 31.12.2018 09:48
Ответ принят как подходящий

Вы не хотите манипулировать псевдоэлементами: after и: before, вы хотите скрыть элемент UL. Что вы можете сделать, так это скрыть UL, когда пользователь щелкает любую ссылку, устанавливающую display на none (и не забудьте после этого удалить свойство).

function GetData(TheClicked,WhichItem) {
  parent = TheClicked.parentElement.parentElement; //get the UL
  parent.style.display = 'none'; //hide it

  //In the working version, here is an Ajax call;
  document.getElementById("MainContainer").innerHTML = 'SomeTextSomeTextSomeTextSomeText';

  //remove the display set before
  setTimeout(function(){
    parent.style.removeProperty('display');
  }, 50)
}

Обратите внимание на тайм-аут: если вы удалите свойство без него, элемент .NavBar не будет проверять состояние hover, и снова появится всплывающее меню.

Несколько предложений:

  • не используйте заглавную букву в начале переменных и функций, оставьте это классам javascript (используйте getData, theClicked и whichItem)
  • некоторые обратные вызовы событий click возвращают false, а некоторые нет, прочтите об объекте event в обратных вызовах и правильном использовании event.preventDefault() вместо возврата false
  • вам не нужно передавать текст в качестве параметра, вы можете получить его с помощью theClicked.innerText, чтобы упростить код

Я пробовал оба решения (@arieljoud и @Armel), и оба выполняют свою работу, и оба мне нравятся. Один из вас вносит предложения, другой - фрагмент. Принятие того или иного (для меня) одинаково, поэтому решение было случайным. Грасиас!

CMArg 31.12.2018 09:48

Другие вопросы по теме