最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - How can I use jQuery for predefined events? - Stack Overflow

programmeradmin0浏览0评论

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>" );
  });

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>" );
  });
Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked Sep 8, 2017 at 13:56 Mojtaba ReyhaniMojtaba Reyhani 4571 gold badge6 silver badges20 bronze badges 2
  • The code you have should work, so long as you're listening for the event on the correct element. You'll need to check the plugin documentation to ensure that - although in mosts cases you'll need to listen to the same element you define the plugin on – Rory McCrossan Commented Sep 8, 2017 at 13:57
  • Many plugins don't use the standard EventEmitter API for events, and implement non-standard or proprietary event syntax. Check the documentation to ensure that .on() or addEventListener() is the intended way to handle custom events for this software. – Patrick Kunka Commented Sep 8, 2017 at 14:06
Add a ment  | 

3 Answers 3

Reset to default 9 +50

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 ments 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./jquery-3.2.1.min.js"></script>
<script src="https://cdn.jsdelivr/gh/stefangabos/Zebra_Accordion/dist/zebra_accordion.min.js"></script>
<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr/gh/stefangabos/Zebra_Accordion/dist/zebra_accordion.min.css">
<link rel="stylesheet" type="text/css" href="https://cdnjs.cloudflare./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/8wzvucgb/

The "Plugin Events" aren't really events, and won't work with on().

You can supply callbacks in the invocation that will be called when the accordion opens and closes.

Their "events" are coded in the initial invocation of the plugin:

var myAccordion = new $.Zebra_Accordion($('.Zebra_Accordion'),{
      onOpen:function(index,$title,$block){…},
      onClose:function(index,$title,$block){…}
});

It's an old-fashioned way of doing things. It's much more flexible of plugins use real events.

What you might need: watch out for dynamically created html. For example

<script>
...
$('#add').click(function() {
  $('#container').append('<div class="item"> new item </div>')
})
$('#container .item').on('click', function() { ... })
...
</script>  
<input id="add" value="Add 1 item" type="button"/>  
<div id="container">
  <div class="item"> click item 1 </div>
  <div class="item"> click item 2 </div>
</div>

The problem is that the dynamically added items will not respond to the click event, because the html didn't exist yet.


What you do, is this:

$('#container').on('click', '.item', function() { ... })

Then, jQuery will listen to a click on #container, and then at click time it will dynamically search the .item children.

发布评论

评论列表(0)

  1. 暂无评论