0

Friends,

Instead of manually init'ing every single instance:

$("#MyChildId1").find("ul.sf-menu").superfish({ delay: 100, speed: 'fast' });
$("#MyChildId2").find("ul.sf-menu").superfish({ delay: 100, speed: 'fast' });
$("#MyChildId3").find("ul.sf-menu").superfish({ delay: 100, speed: 'fast' });

I would like to use multiple (and dynamic) instances of a jQuery plugin (Superfish) and init them with one call on the parent using Event Delegation:

$("#MyParentId").find("ul.sf-menu").superfish({ delay: 100, speed: 'fast' });

But this doesn't work, even though the doc says it now uses Event Delegation on: http://users.tpg.com.au/j_birch/plugins/superfish/

Last bullet item: "•Uses event delegation as of v1.5.1 for greater performance and flexibility."

Any jQuery Geniuses know what's up?

  • Unless the plugin uses something like `return this.each(...` to iterate the passed collection of elements, you can only use it on one single element (and it sucks, the plugin that is). – adeneo Sep 27 '13 at 00:27
  • it should work... from what I saw within the plugin – Arun P Johny Sep 27 '13 at 00:28
  • Yeah, the plugin has this.each(... inside the init... but when I try $("#MyParentId").find("ul.sf-menu")...the children can't call the show() method. Maybe it's because ($el).data('sf-options') is getting set on the parent, and not the children so they can't call the show() method. Doh. – John McMillion Sep 27 '13 at 00:41
  • If it uses this.each(... in the init, what happens when you dynamically insert new children? Do they still bubble up? – John McMillion Sep 27 '13 at 01:00
  • I can confirm, they don't. You only get what is wired up in the init: this.each( at the time of page load. Any children added dynamically lose out on init wire ups. – John McMillion Sep 27 '13 at 01:38

1 Answers1

0

You can select all the menus then loop through them to initiate them.

$("#MyParentId").find("ul.sf-menu").each(function () {
    $(this).superfish({ delay: 100, speed: 'fast' });
});

Documentation for .each(): http://api.jquery.com/each

You could also use:

For example:

var $menus = $("#MyParentId").find("ul.sf-menu");
for (var i = 0, l = $menus.length; i < l; i++) {
    $menus.eq(i).superfish({ delay: 100, speed: 'fast' });
}

The for loop will run slightly faster than a jQuery .each() loop, I believe mostly because the .each() loop creates an IIFE for each iteration (e.g. for (...) { (function () {...})(); }).

Jasper
  • 75,717
  • 14
  • 151
  • 146
  • Is it possible to do it with event delegation? I'm going to be adding some dynamically by updating my viewmodel with knockout. Wondering if the plug-in actually supports event delegation. For some reason I don't even see a reference to delegates inside the plugin, let alone a sample that uses it, yet they specifically say that it uses event delegation now. I must be missing something. – John McMillion Sep 27 '13 at 00:31
  • Look on lines 64, 65, and 75-77 of superfish.js, where it uses `.on()`. That's event delegation. – Barmar Sep 27 '13 at 00:42
  • I'm not familiar with .on()... When I think of event delegation, I use $("#MyParentId").delegate(".child-class", "click", function(e) {... I'm actually not sure if a this.each in a plugin-in init would even wire up dynamically inserted children. – John McMillion Sep 27 '13 at 00:58
  • It's not. The init: this.each(function is the whole problem. It only inits items it finds at the time you load the page. Event delegation typically allows dynamically added children after page load to bubble up. Does anybody have any ideas how to get a jQuery plug-in to support init'ing the plug-in on the parent with event delegation? I've wanted to figure this out for other jQuery plug-ins before too. – John McMillion Sep 27 '13 at 01:32
  • @user2378631 I think you may misunderstand what the authors of the plugin meant by delegated events. This most likely means that all the event handlers for the plugin are bound to a single element rather than to specific elements. This makes it easier for people to customize the plugin and the plugin should initialize faster. What you want to do is initialize new instances of the plugin dynamically. See my answer here for examples on how to initialize the plugin when its HTML is added to the DOM: http://stackoverflow.com/questions/9610267/jquery-on-load-of-dynamic-element/9610396#9610396 – Jasper Sep 27 '13 at 16:03