Как допилить js для выпадающего меню по клику

ЕСТЬ РЕШЕНИЕ ЗАКРЫТО
#1 1 мая 2019 в 15:30
Вопрос сложный, знаю. Есть двухуровневое меню. Это обычное меню в двойке с 2 уровнями. Нужно сделать, что при клике на ссылку верхнего уровня открывался второй уровень. Частично вопрос решил таким кодом:

  1. $(document).click( function(event){
  2. if( $(event.target).closest('.folder > ul').length )
  3. return;
  4. $('.folder.more > ul').slideUp(50);
  5. event.stopPropagation();
  6. });
  7. $('.folder.more > a').click( function() {
  8. $(this).siblings('.folder.more > ul').slideToggle(150);
  9. return false;
  10. });
Работает только для ссылки "Еще", когда пунктов больше, чем можно.

Но тут вдруг откуда ни возьмись появилась новая задача — нужно, чтобы это работало нормально для всех пунктов, потому что у них тоже появились вторые уровни.

Если сделать так:

  1. $(document).click( function(event){
  2. if( $(event.target).closest('.folder > ul').length )
  3. return;
  4. $('.folder > ul').slideUp(50);
  5. event.stopPropagation();
  6. });
  7. $('.folder > a').click( function() {
  8. $(this).siblings('.folder > ul').slideToggle(150);
  9. return false;
  10. });
То почти работает. Почти, потому что подменюшки накладываются один на другой. А надо, чтобы при клике по одному пункту, подменю другого пункта закрывалось.

Например, есть у нас такая структура:
  1. <div id="maimenu">
  2. <ul class="menu">
  3. <li class="folder">
  4. <a class="item">
  5. <span class="wrap">Пункт 1</span>
  6. </a>
  7. <ul>
  8. подменю 1
  9. </ul>
  10. </li>
  11. <li class="folder">
  12. <a class="item">
  13. <span class="wrap">Пункт 2</span>
  14. </a>
  15. <ul>
  16. подменю 2
  17. </ul>
  18. </li>
  19. <li class="folder">
  20. <a class="item">
  21. <span class="wrap">Пункт 3</span>
  22. </a>
  23. <ul>
  24. подменю 3
  25. </ul>
  26. </li>
  27. </ul>
  28. </div>
Нужно сделать так, чтобы при клике по ссылке "Пункт 1" открывалось "подменю 1", при повторном клике чтобы закрывалось. В это же время, если открыто "подменю 2" или "подменю 3" — чтобы они закрывались. Например, кликнули на "Пункт 3", открылось "подменю 3", теперь кликнули на "Пункт 1" — "подменю 3" закрылось, "подменю 1" открылось. Кликнули в любом месте экрана мимо нашего меню — все подменюшки закрылись.

Кто знает? Данке шон.
#2 1 мая 2019 в 16:31
  1.  
  2. <script>
  3. var main_menu = $('#maimenu ul.menu');
  4. $('.folder > a', main_menu).on('click', function(){
  5. $('.folder > ul', main_menu).hide(150);
  6. $(this).siblings('.folder > ul').show(150);
  7. return false;
  8. });
  9. </script>
#3 1 мая 2019 в 17:47
Не, нифига. Немного не то.

Если весь мой код заменить Вашим, то тогда подменю вообще не закрывается.
Если же Вашим кодом заменить только вторую часть моего, то при повторном клике подменю не закрывается, а открывается второй раз. И третий. Теперь, чтобы скрыть подменю нужно кликнуть за пределами меню.
А надо, чтобы было так: нажимаем на ссылку — открывается подменю, нажимаем еще раз — закрывается, если открыто, при нажатии на другую ссылку открытое закрывается, если кликнуть за пределами — закрывается.
#6 3 мая 2019 в 12:11
Го пример на jsfiddle или подобном.
Делать самому лень.

Нагуглил такую тему webformyself.com/forum/index.php/topic/4680/
Там как раз нужный вам closest()
#7 3 мая 2019 в 12:41

нажимаем на ссылку — открывается подменю, нажимаем еще раз — закрывается, если открыто, при нажатии на другую ссылку открытое закрывается, если кликнуть за пределами — закрывается

чебурек дохлэй мыш

Иллюстрация
JS надо почистить… выколупывал от генератора, может чего лишнее есть...

  1.  
  2. <script>
  3.  
  4. var Control = (function ($) {
  5. 'use strict';
  6. return (function () {
  7. this.init = function(label, type, callback) {
  8. var chAttr = label.find('input[type="' +type + '"]').attr('checked');
  9. if (chAttr === 'checked') {
  10. label.addClass('cms-checked');
  11. }
  12.  
  13. label.mouseleave(function () {
  14. $(this).removeClass('hovered').removeClass('active');
  15. });
  16. label.mouseover(function () {
  17. $(this).addClass('hovered').removeClass('active');
  18. });
  19. label.mousedown(function (event) {
  20. if (event.which !== 1) {
  21. return;
  22. }
  23. $(this).addClass('active').removeClass('hovered');
  24. });
  25. label.mouseup(function (event) {
  26. if (event.which !== 1) {
  27. return;
  28. }
  29. callback.apply(this);
  30. $(this).removeClass('active').addClass('hovered');
  31. });
  32. };
  33. });
  34. })(jQuery);
  35.  
  36. jQuery(function($) {
  37. 'use strict';
  38. if (!$('html').hasClass('ie7')) {
  39. return;
  40. }
  41. $('ul.cms-vmenu li:not(:first-child),ul.cms-vmenu li li li:first-child,ul.cms-vmenu>li>ul').each(function () { $(this).append('<div class="cms-vmenu-separator"> </div><div class="cms-vmenu-separator-bg"> </div>'); });
  42. });
  43.  
  44. jQuery(function() {
  45. 'use strict';
  46. setOpenSubmenuWithNoReload({vMenuClass: "cms-vmenu", activeClass: "active", hoveredClass: "hovered"});
  47. });
  48.  
  49. var setOpenSubmenuWithNoReload = (function($) {
  50. 'use strict';
  51. return (function(vMenuInfo) {
  52. $("ul." + vMenuInfo.vMenuClass + " li").each(function () {
  53. var item = $(this);
  54. item.children("a").bind("click", function(e) {
  55. var link = $(this);
  56. var simple = link.siblings("ul").length === 0;
  57. link.parent().siblings().children("ul." + vMenuInfo.activeClass).slideUp(function() {
  58. $(this).find("li, a, ul").removeClass(vMenuInfo.activeClass);
  59. $(this).removeClass(vMenuInfo.activeClass).siblings("a").removeClass(vMenuInfo.activeClass);
  60. $(this).css("display", "");
  61. });
  62. link.parent().siblings().children("a." + vMenuInfo.activeClass).removeClass(vMenuInfo.activeClass);
  63. link.parent().siblings().removeClass(vMenuInfo.activeClass);
  64. if (simple && !link.hasClass(vMenuInfo.activeClass)) {
  65. link.addClass(vMenuInfo.activeClass).parent().addClass(vMenuInfo.activeClass);
  66. }
  67. if (!simple) {
  68. if (link.hasClass(vMenuInfo.activeClass)) {
  69. link.siblings("ul").slideUp("fast", function() {
  70. $(this).removeClass(vMenuInfo.activeClass).siblings("a").removeClass(vMenuInfo.activeClass).parent().removeClass(vMenuInfo.activeClass);
  71. $(this).css("display", "");
  72. });
  73. } else {
  74. link.siblings("ul").slideDown("fast", function() {
  75. $(this).addClass(vMenuInfo.activeClass).siblings("a").addClass(vMenuInfo.activeClass).parent().addClass(vMenuInfo.activeClass);
  76. $(this).css("display", "");
  77. });
  78. }
  79.  
  80. e.preventDefault();
  81. return false;
  82. }
  83. });
  84. });
  85. });
  86. })(jQuery);
  87.  
  88. </script>
  89.  

  1.  
  2. <style>
  3. .cms-vmenublockcontent {
  4. margin: 0 auto;
  5. }
  6.  
  7. ul.cms-vmenu, ul.cms-vmenu ul {
  8. list-style: none;
  9. display: block;
  10. }
  11.  
  12. ul.cms-vmenu, ul.cms-vmenu li {
  13. display: block;
  14. margin: 0;
  15. padding: 0;
  16. width: auto;
  17. line-height: 0;
  18. }
  19.  
  20. ul.cms-vmenu {
  21. margin-top: 0;
  22. margin-bottom: 0;
  23. }
  24.  
  25. ul.cms-vmenu ul {
  26. display: none;
  27. margin: 0;
  28. padding: 0;
  29. position: relative;
  30. }
  31.  
  32. ul.cms-vmenu ul.active {
  33. display: block;
  34. }
  35.  
  36. ul.cms-vmenu>li>a {
  37. background: #262626;
  38. padding: 0 15px;
  39. margin: 0 auto;
  40. color: #8F8F8F;
  41. min-height: 30px;
  42. line-height: 30px;
  43. }
  44.  
  45. ul.cms-vmenu a {
  46. display: block;
  47. cursor: pointer;
  48. z-index: 1;
  49. font-size: 13px;
  50. font-family: 'Droid Serif', Arial, 'Arial Unicode MS', Helvetica, Sans-Serif;
  51. font-weight: normal;
  52. font-style: normal;
  53. text-decoration: none;
  54. position: relative;
  55. }
  56.  
  57. ul.cms-vmenu li {
  58. position: relative;
  59. }
  60.  
  61. ul.cms-vmenu>li {
  62. margin-top: 0;
  63. }
  64.  
  65. ul.cms-vmenu>li>ul {
  66. padding: 0;
  67. margin-top: 0;
  68. margin-bottom: 0;
  69. }
  70.  
  71. ul.cms-vmenu>li:first-child {
  72. margin-top: 0;
  73. }
  74.  
  75. ul.cms-vmenu>li>a:hover, ul.cms-vmenu>li>a.active:hover {
  76. background: #35A9D0;
  77. padding: 0 15px;
  78. margin: 0 auto;
#8 3 мая 2019 в 13:56
Дмитрий Баринов, у Вас сложно очень.

Нагуглил такую тему

Zau4man
Блин, как у Вас получилось?)))

Короче, Ваш пример очень помог. Пришлось, правда, в шаблон меню вставку сделать аттрибута rel с уникальным значением для каждого пункта и еще пара вставок. Но это было просто))
  1. <a rel="i<?php echo $item['id']; ?>" class="item opendm"
  2. ........
  3. <ul class="dropdown-menu i<?php echo $item['id']; ?>">
Остался маа-аааленький нюансик))) При клике на ссылку ей добавляется класс, чтобы подсветить, когда эта кнопка активная, т.е., когда ее подменю открыто. Так вот, если кликнуть по ссылке, то ей добавляется класс openmore, если кликнуть по ней же, то класс удаляется, если кликнуть за пределами меню, то класс удаляется. Все правильно и хорошо. Но если кликнуть по другой ссылке, то класс openmore у текущей нифига не удаляется. Перепробовал 100500 вариантов, не срабатывает нифига))

Вот код:
  1. var res = $(".dropdown-menu");
  2. $('[rel^="i"]').on("click", funk);
  3.  
  4. $(document).click(function(e) {
  5. if ($(e.target).closest(res).length || $(e.target).closest('.folder > a').length) return;
  6. res.hide();
  7. e.stopPropagation();
  8. $('.folder > a').removeClass('openmore');
  9. });
  10.  
  11. function funk(){
  12. var link = $(this).attr('rel'),
  13. el = $('.dropdown-menu.'+link);
  14. ek = $('.opendm.'+link);
  15. $(this).removeClass('openmore');
  16.  
  17. if(el.css("display") == "none"){
  18. res.hide();
  19. el.slideDown(150);
  20. $(this).addClass('openmore');
  21. } else {
  22. el.hide();
  23. }
  24. }
Как в нем сделать так, чтобы при клике по другой ссылке у текущей удалялся класс openmore
#9 3 мая 2019 в 14:31
Решение вот (может кому-нибудь пригодится):

1. В файле templates/шаблон/assets/ui создать файл menu-dropdown.tpl.php, скопировать в него код из файла menu.tpl.php. Найти в нем
  1.  
  2. <a class="item" <?php echo $data_attr; ?> href="<?php echo !empty($item['url']) ? htmlspecialchars($item['url']) : 'javascript:void(0)'; ?>" <?php if ($onclick) { ?>onclick="<?php echo $onclick; ?>"<?php } ?> <?php if ($target) { ?>target="<?php echo $target; ?>"<?php } ?>>
и заменить на
  1. <a rel="i<?php echo $item['id']; ?>" class="item opendm" <?php echo $data_attr; ?> href="<?php echo !empty($item['url']) ? htmlspecialchars($item['url']) : 'javascript:void(0)'; ?>" <?php if ($onclick) { ?>onclick="<?php echo $onclick; ?>"<?php } ?> <?php if ($target) { ?>target="<?php echo $target; ?>"<?php } ?>>
Еще в этом же файле найти
  1. <?php if ($item['childs_count'] > 0) { ?><ul><?php } ?>
и заменить на
  1. <?php if ($item['childs_count'] > 0) { ?><ul class="dropdown-menu i<?php echo $item['id']; ?>"><?php } ?>
В самый низ этого файла вставить:

  1. <script language="JavaScript">
  2. (function($){
  3. var res = $(".dropdown-menu");
  4. $('[rel^="i"]').on("click", funk);
  5.  
  6. $(document).click(function(e) {
  7. if ($(e.target).closest(res).length || $(e.target).closest('.folder > a').length) return;
  8. res.hide();
  9. e.stopPropagation();
  10. $('.openmore').removeClass('openmore');
  11. });
  12.  
  13. function funk(){
  14. var link = $(this).attr('rel'),
  15. el = $('.dropdown-menu.'+link);
  16. ek = $('.opendm.'+link);
  17. $(this).removeClass('openmore');
  18.  
  19. if(el.css("display") == "none"){
  20. res.hide();
  21. el.slideDown(150);
  22. $('.openmore').removeClass('openmore');
  23. $(this).addClass('openmore');
  24. } else {
  25. el.hide();
  26. }
  27. }
  28. })(jQuery);
  29. </script>
В настройках виджета меню во вкладке "Опции" выбрать шаблон списка меню


И сохранить. Стили добавить по вкусу.

Всем спасибо! Решено.
Используя этот сайт, вы соглашаетесь с тем, что мы используем файлы cookie.