gwar9
gwar9

Reputation: 1082

How to pass defined function into jQuery click event?

I have a drawer menu that expands on btn click, what I am trying to achieve is closing the menu when a user clicks on the sidenav-body class which covers the whole body.

Here is the base html and js

<div class="offcanvas-body sidenav-body">
    <main id="main-content" role="main">
        <div class="container-fluid short-section-row">
           <div class="row">
               <div class="side-nav-btn navbar-btn js-side-nav-btn" aria-expanded="false" aria-label="Open Side Navigation" aria-controls="SecondaryMenu">Explore This Section <span class="svg-sprite -hamburger"><svg role="img" aria-label="[object Object]"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#hamburger"></use></svg></span></div>
               <nav class="side-nav col-sm-2" role="Secondary navigation" aria-label="Side Navigation" aria-hidden="true" id="SecondaryMenu">
                   <div class="side-nav__control-bar">
                       <button class="navbar-btn js-side-nav-btn btn btn-primary pull-right" aria-expanded="false" aria-label="Close Side Navigation" aria-controls="SecondaryMenu" tabindex="-1"><span class="svg-sprite -close"><svg role="img" aria-label="close secondary nav"><use xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="#close"></use></svg></span> Menu</button>
                   </div>
                   // some ul and li items
               </nav>
           </div>
        </div>
    </main>
</div>

How I defined classes

this.$body = $(el);
this.$sideNavBody = $('.sidenav-body');
this.$sideNav = $('.side-nav');
this.$controls = $('.side-nav button');
this.$sideNavBtn = $('.js-side-nav-btn');

I have a toggle function on btn click

sideNavBodyToggleEvent(){
    // if the nav is open, run close event
    if(this.$body.hasClass('side-is-open')) {
        this.sideNavBodyCloseEvent();
    } else {
        this.sideNavBodyOpenEvent();
      }
    }

And those conditional functions are defined like so

sideNavBodyCloseEvent () {
     this.$body.removeClass('side-is-open');
     // always clear the 'opened state' of any open menus
     this.$sideNavSection.removeClass('side-is-open');
     $(this.$controls).attr('tabindex', '-1');
     $(this.$sideNav).attr('aria-hidden', 'true');
     $(this.$sideNavBtn).attr('aria-expanded', 'false');
     $(this.$sideNavSectionToggle).removeClass('side-is-open');
     // unbind the pushed body click event
     this.$sideNavBody.off();
    }

sideNavBodyOpenEvent() {
      this.$body.addClass('side-is-open');
      $(this.$sideNav).attr('aria-hidden', 'false');
      $(this.$controls).removeAttr('tabindex');
      $(this.$sideNavBtn).attr('aria-expanded', 'true');
      // bind an event on the div containing the pushed body
      // original code left by prev dev was this.$sideNavBody.offClick.bind(this) and doesnt work as I think its trying to run both functions at once (the menu doesnt even open);
      //below I am just trying to test if the click event even makes it to this.$.sideNavBody which is the .sidenav-body class and the section I want users to be able to click to close
      $(this.$sideNavBody).click(function(e){
          console.log(e);
      });
    }

The open function works and the drawer menu slides out but my attempt at closing it was as follows

$(this.$sideNavBody).click(function(e){
          $(this.sideNavBodyCloseEvent());
          console.log(e);
});

Which returns this error Uncaught TypeError: this.sideNavBodyCloseEvent is not a function everytime the .sidenav-body / $sideNavBody is clicked

How can I pass is this sideNavBodyCloseEvent() function on that element click?

When adding the bit of code to close the menu when click on the .sidenav body the menu closes when it encounters this code from jquery

if ( !( eventHandle = elemData.handle ) ) { eventHandle = elemData.handle = function( e ) { // Discard the second event of a jQuery.event.trigger() and // when an event is called after a page has unloaded return typeof jQuery !== "undefined" && jQuery.event.triggered !== e.type ? jQuery.event.dispatch.apply( elem, arguments ) : undefined; }; }

I have never seen or had this problem before any suggestions?

Upvotes: 0

Views: 457

Answers (2)

PeterMader
PeterMader

Reputation: 7275

Does this work?

$(this.$sideNavBody).click(function(e){
    $(this.sideNavBodyCloseEvent());
    console.log(e);
}.bind(this));

The inner function has its own this object, which doesn't have the sideNavBodyCloseEvent method. To use the this object of the outer function in the inner function, use bind.

Normally, you have an initialisation function that binds the necessary event handlers:

init () {
  this.$sideNavBtn.click(this.sideNavBodyOpenEvent.bind(this));
  this.$sideNavBody.click(this.sideNavBodyCloseEvent.bind(this));
}

Upvotes: 1

Richard   Housham
Richard Housham

Reputation: 1680

How about doing this a different way. I think I've made a mistake somewhere in there with the elements, but passing this element as a parameter is the main change.

$body = $(el);
$sideNavBody = $('.sidenav-body');
$sideNav = $('.side-nav');
$controls = $('.side-nav button');
$sideNavBtn = $('.js-side-nav-btn');

$sideNavBody.click(function(e){
          sideNavBodyCloseEvent($(this))
          console.log(e);
});

sideNavBodyCloseEvent (element) {
     element.$body.removeClass('side-is-open');
     // always clear the 'opened state' of any open menus
     element.$sideNavSection.removeClass('side-is-open');
     $controls.attr('tabindex', '-1');
     $sideNav.attr('aria-hidden', 'true');
     $sideNavBtn.attr('aria-expanded', 'false');
     $sideNavSectionToggle.removeClass('side-is-open');
     // unbind the pushed body click event
     $sideNavBody.off();
    }

Upvotes: 0

Related Questions