0

I am writing an event delegating plugin that takes 4 params:

  • context = String selector
  • child element = String selector
  • event = String
  • fn = Function to call

The plugin must delegate events to the child element if the parent is present in the DOM so far so good...

The problem arises when the context element is the same as the child element. Delegate no longer works because it expects the child passed to be a child of the context.

Here is an example input that fails:

  • context = "ul"
  • child element = "ul.active"
  • event = "click"

you cant do $('ul').on('click', 'ul.active', fn()) since sometimes 'ul.active' will be the same as the 'ul'.

One solution i can think of might be:

var $context = $('ul');
$(document).on('click', 'ul.active', function(e){
   var $target = $(e.target);
   if($target.is($context) || $target.closest($context).length){
      fn()
   }
})

I wonder if it might be better to do the check of 'is child == context' before binding the delegation events and bind them appropriately to the situation

jcolebrand
  • 15,889
  • 12
  • 75
  • 121
mkoryak
  • 57,086
  • 61
  • 201
  • 257
  • I'm confused what you're really asking. Also, the example at the bottom fails closure. – jcolebrand Jun 19 '12 at 15:08
  • This question sounds really familiar, as if it were asked on the jQuery forums, but I can't find it. Basically, event delegation doesn't work that way. A delegated event delegates from a parent element, it can't delegate from a parent element to the same parent. At that point it wouldn't be a delegated event. – Kevin B Jun 19 '12 at 15:12
  • Here it is: https://forum.jquery.com/topic/event-selector-doesn-t-apply-to-the-original-element-bug-or-feature – Kevin B Jun 19 '12 at 15:17
  • 1
    I see what you are doing now... But it looks like a lot of extra work when you could just bind to the document to begin with instead of hiding that behind a plugin. – Kevin B Jun 19 '12 at 15:28
  • @jcolebrand: the example at the bottom is psuedocode. – mkoryak Jun 19 '12 at 15:28
  • yes, jquery.on doesnt work in this case. what im asking is: given this case, what is the best way do accomplish what i want to do? is it to delegate from document, or is there another way? – mkoryak Jun 19 '12 at 15:29
  • What exactly are you trying to do? It looks like you are trying to delegate events to elements that you don't know what their parents will be, which would be a good case for delegating from the document. – Kevin B Jun 19 '12 at 15:30
  • @KevinB: thats the problem with SO, i dont want to go into the reason why im doing all of this because it would take too much time, and really has nothing to do with my question. You will just have to take my word that i have a really good reason – mkoryak Jun 19 '12 at 15:30
  • @KevinB: yeah delegating from the document seems like the answer here. i was hoping that someone might have a better way. I am a bit annoyed that this one requirement means that i cant delegate from `$(context)` – mkoryak Jun 19 '12 at 15:32
  • Yeah, if context has to be delegated too, it has to come from a parent of the context that exists when you initialize the plugin. The document is the only point that will definitely exist in all cases unless you write it for a specific use where the document has a `#content` div for example. – Kevin B Jun 19 '12 at 15:36

1 Answers1

0

I'm not saying this is a great solution, but it's the only way I can think of that isn't delegating up to $(document)

var parent = 'ul';
var child = 'ul.active';

$(parent).on('click', child, function() {
    console.log('ul.active clicked')
})​;

$(child)
    .filter(function(){
        return $(this).parents(parent).length == 0;
    })
    .on('click', function() {
        console.log('ul.active clicked')
    });​

You could probably do the conditions better - just typing as I think :)

Stuart Burrows
  • 10,824
  • 2
  • 34
  • 33