Mojtaba Reyhani Mojtaba Reyhani - 28 days ago 7
jQuery Question

How can I use jQuery for predefined events?

Are there any standard rules for implementing predefined events in a jQuery plugin?

For example, the special case of Zebra Accordion plugin (a tiny accordion plugin for jQuery) or any other plugin defines some events like below:

Zebra Accordion Events:


onClose: Event fired after a tab is collapsed.

onOpen: Event fired after a tab is collapsed.


In this case if I wanted to add a div with special Font Awesome characters (such as fa-chevron-down) after the box title when
collapsed
(Closed, collapsed state) and remove that character and replace it with a new character (like fa-chevron-up) near the box title when
expended
(opened state). I would like to finally add some functionality like jQuery Accordion to it. I've tried with the below code but it appears something is wrong:

$('.Zebra_Accordion').on('onOpen', function(e) {
$(this).append( "<span class='fa fa-chevron-down'></span>" );
});

$('.Zebra_Accordion').off('onClose', function(e) {
$(this).append( "<span class='fa fa-chevron-up'></span>" );
});

Answer Source

Most jQuery plugins have an options object that you pass in. In here you can define the properties you want to set including event handlers.

The documentation for the zebra accordion events says for each of the events the plugin provides:

The callback function takes 3 arguments:

  • the tab's position in the accordion (0 based)
  • the associated title element, as a jQuery object
  • the tab, as a jQuery object

I've just given them 3 suitable names, and used the second argument (which I arbitrarily named hdr).

As noted in the documentation the hdr argument returned is a jQuery object wrapping the <dt> element (at least in my example). On this object I called the jQuery function .find() to find the element(s) inside that <dt> having the fa-chevron-* class, and then I switch the classes on that span by chaining further jQuery functions.

As noted in the comments you can do it perfectly well in-line like:

var accordian = new $.Zebra_Accordion($('.Zebra_Accordion'), {
    collapsible: true,
    onBeforeOpen: function(index, hdr, body) {
       hdr.find(".fa-chevron-down").removeClass('fa-chevron-down').addClass('fa-chevron-up');
    },
    onBeforeClose: function(index, hdr, body) {
       hdr.find(".fa-chevron-up").removeClass('fa-chevron-down').addClass('fa-chevron-down');
    }
});

And in this particular case I would, but I wanted to illustrate what to do when the handlers have more code, in which case making them separate functions makes for better readability.

Don't forget to use console.log() a lot - it is a JavaScript developer's best friend.

To check what this Zebra Accordion was providing me I did the following first:

onBeforeOpen: function(index, hdr, body) {
       console.log("onBeforeOpen", index, hdr, body);
},

This output shows up in the browser's developer's console.

Here's my demo putting it all together:

$(function() {
  
  // add default chevrons here so they only get appended once
  $(".Zebra_Accordion dt").append("<span class='chevron fa fa-chevron-down'></span>");

  // set up the according options
  var accordian = new $.Zebra_Accordion($('.Zebra_Accordion'), {
    collapsible: true,
    onBeforeOpen: showCollapseChevron,
    onBeforeClose: showExpandChevron
  });
  
  function showExpandChevron(index, hdr, body) {
      hdr.find(".fa-chevron-up").removeClass('fa-chevron-up').addClass('fa-chevron-down');
  }
  
  function showCollapseChevron(index, hdr, body) {
      hdr.find(".fa-chevron-down").removeClass('fa-chevron-down').addClass('fa-chevron-up');
  }
  
});
dl.Zebra_Accordion { width: 100% }
dl.Zebra_Accordion dt { background: #000; color: #FFF; font-weight: bold; padding: 5px }
dl.Zebra_Accordion dd { background: #EFEFEF; padding: 15px; margin: 1px 0 } 
dl.Zebra_Accordion dt.Zebra_Accordion_Expanded { background: #C40000 }

.chevron {
  margin-left: 5px;
}
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/gh/stefangabos/Zebra_Accordion/dist/zebra_accordion.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/stefangabos/Zebra_Accordion/dist/zebra_accordion.min.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css">

<dl class="Zebra_Accordion">
  <dt>Lorem ipsum dolor sit amet consectetuer</dt>
  <dd>
    Lorem ipsum dolor sit amet consectetuer facilisis lacinia sapien ac et. Quis hendrerit neque congue pretium iaculis justo laoreet orci elit condimentum. Eros natoque Curabitur accumsan eget quis porttitor Sed Vestibulum amet sed.
  </dd>
  <dt>Lorem ipsum dolor sit amet consectetuer</dt>
  <dd>
    Lorem ipsum dolor sit amet consectetuer facilisis lacinia sapien ac et. Quis hendrerit neque congue pretium iaculis justo laoreet orci elit condimentum. Eros natoque Curabitur accumsan eget quis porttitor Sed Vestibulum amet sed.
  </dd>
  <dt>Lorem ipsum dolor sit amet consectetuer</dt>
  <dd>
    Lorem ipsum dolor sit amet consectetuer facilisis lacinia sapien ac et. Quis hendrerit neque congue pretium iaculis justo laoreet orci elit condimentum. Eros natoque Curabitur accumsan eget quis porttitor Sed Vestibulum amet sed.
  </dd>
  <dt>Lorem ipsum dolor sit amet consectetuer</dt>
  <dd>
    Lorem ipsum dolor sit amet consectetuer facilisis lacinia sapien ac et. Quis hendrerit neque congue pretium iaculis justo laoreet orci elit condimentum. Eros natoque Curabitur accumsan eget quis porttitor Sed Vestibulum amet sed.
  </dd>
</dl>

External Demo https://jsfiddle.net/8wzvucgb/