Why is my click() function working only on resize?

Viewed 72

I am getting insane. As you can see at below code snippet - everything works well. But not in my project. In my project works only code in resize(). When I resize window - ok, it's nice, I can add and remove class 'open' by click on item. But if I refresh page and not resize window - I cant't add class. Can't do nothing. I am spending few hours with this thing. Can somebody help me? Why isn't it working?

(function ($) {
  $('.nav-item').on('click', function() {
    $(this).toggleClass('open');
    $(this).siblings().removeClass('open');
  });

  $(window).resize(function() {
    if($(window).width() < 1200) {
      $('.nav-item').on('click', function() {
        $(this).toggleClass('open');
        $(this).siblings().removeClass('open');
      });
    }
  });
})(jQuery);
.open {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul class="main-menu">
  <li class="nav-item">
     <span class="nav-link">Menu item 1</span>
  </li>
  <li class="nav-item">
     <span class="nav-link">Menu item 2</span>
     <ul class="dropdown-menu">
        <li class="dropdown-item">
           <span>Menu item 2 subitem 1</span>
        </li>
        <li class="dropdown-item">
           <span>Menu item 2 subitem 2</span>
        </li>
     </ul>
  </li>
  <li class="nav-item">
     <span class="nav-link">Menu item 3</span>
     <ul class="dropdown-menu">
        <li class="dropdown-item">
           <span>Menu item 3 subitem 1</span>
        </li>
        <li class="dropdown-item">
           <span>Menu item 3 subitem 2</span>
        </li>
     </ul>
  </li>
</ul>

I work with Drupal 8 CMS (if it's important - but I worked with jQuery, click() and Drupal milion of times and it was always fine.

2 Answers

The reason it works in the snippet but not your code is because the SO snippets automatically place jQuery logic within a document.ready event handler, which ensures that the DOM has loaded before the code runs.

However your code is running in an IIFE, not a document.ready event handler, so you try to bind the events to elements that don't exist yet. It's not until the resize event occurs that the event is bound and starts working.

To fix this replace the IIFE with a document.ready handler:

jQuery(function($) {
  $('.nav-item').on('click', function() {
    $(this).toggleClass('open').siblings().removeClass('open');
  });
})
.open {
  color: red;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<ul class="main-menu">
  <li class="nav-item">
    <span class="nav-link">Menu item 1</span>
  </li>
  <li class="nav-item">
    <span class="nav-link">Menu item 2</span>
    <ul class="dropdown-menu">
      <li class="dropdown-item">
        <span>Menu item 2 subitem 1</span>
      </li>
      <li class="dropdown-item">
        <span>Menu item 2 subitem 2</span>
      </li>
    </ul>
  </li>
  <li class="nav-item">
    <span class="nav-link">Menu item 3</span>
    <ul class="dropdown-menu">
      <li class="dropdown-item">
        <span>Menu item 3 subitem 1</span>
      </li>
      <li class="dropdown-item">
        <span>Menu item 3 subitem 2</span>
      </li>
    </ul>
  </li>
</ul>

I searched another few hours in the Internet and I found a solution with Drupal.behaviours... I don't know how and why it works, why in this project this simple jQuery code (from below and from my post, it's the same) didn't work, but in another Drupal projects works well... I don't know. Maybe someone could tell me. I don't know.

Version with:

jQuery(function($) {
  ...
});

instead of:

(function ($) {
  ...
})(jQuery);

also didn't work.

So I deleted all my code:

(function ($) {
  $('.nav-item').on('click', function() {
    $(this).toggleClass('open');
    $(this).siblings().removeClass('open');
  });

  $(window).resize(function() {
    if($(window).width() < 1200) {
      $('.nav-item').on('click', function() {
        $(this).toggleClass('open');
        $(this).siblings().removeClass('open');
      });
    }
  });
})(jQuery);

and I added this code:

(function ($) {
Drupal.behaviors.navclick = {
    attach: function (context, settings) {
      $('.nav-item', context).click(function () {
        $(this).toggleClass('open').siblings().removeClass('open');
      });
    }
  };
})(jQuery);

And now it works, and on resizing the window, and after just firing the page (previously it didn't work on just firing the page). Why? I don't know.

Related