Закрытие всплывающего подменю после щелчка без обновления страницы - PullRequest
2 голосов
/ 05 мая 2019

У меня есть система меню навигации с подменю, как в примере ниже.В подменю (отображается при наведении курсора на «Двухуровневый») есть опция «Только AJAX».Если выбран этот параметр, будет запущена подпрограмма ajax, и я хочу, чтобы раскрывающееся меню немедленно снова скрывалось (т. Е. При нажатии этой опции подменю должно исчезнуть).

Я пробовал jQuery hide(), но это навсегда отключает подменю (т. е. при перемещении мыши назад к строке меню оно больше не открывается) .

Я также попытался hide(), а затем show(), но это делает подменю видимым даже после удаления мыши.

mouseleave() и mouseout() звучали многообещающе, но ни один из них, похоже, ничего не делает, независимо от того, к какому связанному элементу я их применяю.

Вот упрощенный код:

$(function() {
  $('.ajax').click(function(event) {
    event.preventDefault(); //to keep from jumping to top of page
    //$(this).closest('ul').hide(); /* this breaks the menu */
    /* none of these do anything I can see */
    $(this).mouseleave();
    $(this).parent().mouseleave();
    $(this).parent().parent().mouseleave();
    $(this).trigger("mouseout");
    $(this).parent().trigger("mouseout");
    $(this).parent().parent().trigger("mouseout");
    $(this).trigger("mouseleave");
    $(this).parent().trigger("mouseleave");
    $(this).parent().parent().trigger("mouseleave");

    /* do stuff with AJAX */
  });
});
ul.nav {
  background-color:rgb(88,57,7);
  list-style-type: none;
  text-align: center;
  vertical-align: middle;
  min-height: 30px;
  position:sticky;
  top:0;
}
ul.nav li {
  display: inline-block;
  position: relative;
}
ul.nav-sub { /* second level menus */
  display: none;
  position: absolute;
  background-color:rgb(88,57,7);
  margin: -4px 0 0 15px;
  border: 1px solid LightSteelBlue;
  padding: 0;
  border-radius: 0;
  text-align: left;
  min-height: 0;
}
ul.nav li:hover ul {
  display: block;
  z-index:100;
}
ul.nav-sub li {
  display: block;
}
ul.nav a {
  display: block;
  color: LightSteelBlue;
  padding: 10px 15px;
  margin: 0;
  font-family: arial, helvetica, sans-serif;
  font-weight: bold;
  text-decoration: none;
  white-space:nowrap;
}
ul.nav a:hover {
  background-color: rgb(132,78,12);
  color: White;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<ul class="nav">
  <li><a href="file1.php" target="_top">Simple</a></li>
  <li>
    <a href="#">Two-level &#x25BC;</a>
    <ul class="nav-sub">
      <li><a href="file2.php" target="_top">Go to a page</a></li>
      <li><a class="ajax" href="#">Do AJAX only</a></li>
      <li><a href="file3.php">Go to another page</a></li>
    </ul>
  </li>
</ul>

Кодовый код здесь: https://codepen.io/OsakaWebbie/pen/yWLXeV

Ответы [ 2 ]

0 голосов
/ 08 мая 2019

Я не хочу доверять себе ответ, но после ответа Голды мне пришлось провести гораздо больше исследований, прежде чем я получил что-то, что сработало бы для меня, и мое решение могло бы быть полезным для других, кто прочитает это позже.Мое настоящее меню содержит несколько элементов всех типов, и даже вся разметка навигационного меню дублируется, поэтому я не могу использовать идентификаторы.Кроме общего вывода о том, что необходимо будет заменить функциональность псевдоэлемента CSS hover на JS, я не стал использовать код Голды.

Вещи, которые я узнал:

  • mouseenter и mouseleave - лучшие события для этого, чем mouseover и mouseout, потому что mouseover и mouseout продолжают стрелять в горячем беспорядке, когда мышь перемещается между элементами в подменю (и даже иногдане стреляет, если я двигаюсь слишком быстро!).[Ответ Голды работал с mouseover/mouseout до тех пор, пока они были пойманы на двух элементах в подменю и идентификаторы были назначены для всего.Я часами пытался найти правильные селекторы jQuery, которые бы делали то же самое с иерархией и классами DOM, но безрезультатно.]
  • Отличное объяснение различия между mouseover/mouseout и mouseenter/mouseleave находится по адресу: https://javascript.info/mousemove-mouseover-mouseout-mouseenter-mouseleave
  • Я узнал о необязательном втором аргументе для селекторов jQuery: context.$("ul",this) означает ul потомка (ей) $(this), который отлично сработал для этого.

Таким образом, решение состоит в том, чтобы подняться на уровень до <li> родителя подменюи поймать mouseenter и mouseleave там.Это приводит к гораздо меньшей специальной разметке, поэтому будущие модификации структуры меню с меньшей вероятностью будут иметь ошибки из-за неуместного класса или двух.Единственный дополнительный класс, который мне был нужен, был class="hassub" на вершине <li>.На самом деле, я даже не ссылаюсь на класс «nav-sub» в jQuery - он мне все еще нужен только для CSS.Первоначально я думал, что применил бы jQuery только к подменю, содержащим ссылки AJAX (потому что CSS hover работал без него), но проще позволить jQuery работать со всеми подменю, поэтому CSS ul.nav li:hover ul { display: block; } больше не нужен,Вот код с расширенной разметкой, которая будет немного более реалистичной:

$(function() {
  $(".hassub").mouseenter(function() { $("ul",this).show(); });
  $(".hassub").mouseleave(function() { $("ul",this).hide(); });
  
  $('.ajaxlink').click(function() { $(this).closest('ul').hide(); });
});
ul.nav {
  background-color:rgb(88,57,7);
  list-style-type: none;
  text-align: center;
  vertical-align: middle;
  min-height: 30px;
  position:sticky;
  top:0;
}
ul.nav li {
  display: inline-block;
  position: relative;
}
ul.nav-sub {
  display: none;
  position: absolute;
  background-color:rgb(88,57,7);
  margin: -4px 0 0 15px;
  border: 1px solid LightSteelBlue;
  padding: 0;
  border-radius: 0;
  text-align: left;
  min-height: 0;
  z-index:100;
}
ul.nav-sub li {
  display: block;
}
ul.nav a {
  display: block;
  color: LightSteelBlue;
  padding: 10px 15px;
  margin: 0;
  font-family: arial, helvetica, sans-serif;
  font-weight: bold;
  text-decoration: none;
  white-space:nowrap;
}
ul.nav a:hover {
  background-color: rgb(132,78,12);
  color: White;
}
/*ul.nav li:hover ul {
display: block;
}*/
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<ul class="nav">
  <li><a href="file1.php">solo page</a></li>
  <li class="hassub">
    <a href="#">submenu1 (mixed) &#x25BC;</a>
    <ul class="nav-sub">
      <li><a href="file2.php">page 1a</a></li>
      <li><a href="file3.php">page 1b</a></li>
      <li><a class="ajaxlink" href="#">ajax 1-1</a></li>
      <li><a href="file2.php">page 1c</a></li>
      <li><a href="file3.php">page 1d</a></li>
    </ul>
  </li>
  <li class="hassub">
    <a href="#">submenu2 (only pages) &#x25BC;</a>
    <ul class="nav-sub">
      <li><a href="file2.php">page 2a</a></li>
      <li><a href="file3.php">page 2b</a></li>
    </ul>
  </li>
  <li id="hassub3" class="hassub">
    <a href="#">submenu3 (only ajax) &#x25BC;</a>
    <ul id="sub3" class="nav-sub">
      <li><a class="ajaxlink" href="#">ajax 3-1</a></li>
      <li><a class="ajaxlink" href="#">ajax 3-2</a></li>
    </ul>
  </li>
</ul>
0 голосов
/ 06 мая 2019

Надеюсь, вам поможет следующий ответ.Я установил идентификаторы для ссылки меню, подменю и ссылки Do AJAX.Я показал меню, используя событие перемещения, и скрыл его, используя событие mouseout

$(function() {
$("#twoLink, #subMenu").mouseover(function(){
 $("#subMenu").show();
});

$("#twoLink, #subMenu").mouseout(function(){
 $("#subMenu").hide();
});

 $("#doAjaxLink").click(function(){
    $("#subMenu").hide();
  });
});
ul.nav {
  background-color:rgb(88,57,7);
  list-style-type: none;
  text-align: center;
  vertical-align: middle;
  min-height: 30px;
  position:sticky;
  top:0;
}
ul.nav li {
  display: inline-block;
  position: relative;
}
ul.nav-sub { /* second level menus */
  display: none;
  position: absolute;
  background-color:rgb(88,57,7);
  margin: -4px 0 0 15px;
  border: 1px solid LightSteelBlue;
  padding: 0;
  border-radius: 0;
  text-align: left;
  min-height: 0;
}
ul.nav li:hover ul {
  display: block;
  z-index:100;
}
ul.nav-sub li {
  display: block;
}
ul.nav a {
  display: block;
  color: LightSteelBlue;
  padding: 10px 15px;
  margin: 0;
  font-family: arial, helvetica, sans-serif;
  font-weight: bold;
  text-decoration: none;
  white-space:nowrap;
}
ul.nav a:hover {
  background-color: rgb(132,78,12);
  color: White;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js"></script>

<ul class="nav">
  <li><a href="file1.php" target="_top">Simple</a></li>
  <li>
    <a id="twoLink" href="#">Two-level &#x25BC;</a>
    <ul id="subMenu" class="nav-sub">
      <li><a href="file2.php" target="_top">Go to a page</a></li>
      <li><a id="doAjaxLink" class="ajax" href="#">Do AJAX only</a></li>
      <li><a href="file3.php">Go to another page</a></li>
    </ul>
  </li>
</ul>
...