1

I'm having some problems with the handler callback using .delegate() in jQuery. This setup uses 2 files- on where $B is created, and the other a simple $(doc).ready file.

I have an SVG file with a bunch (50+) of <g> tags I need to track when I click, rollover, rollout, etc. Instead of attaching the functions to the <g> nodes, delegate looked like a cleaner option.

However, I'm running into an issue which I think is my relative lack of knowledge on JavaScript.

Here's the setup for my main ready() file:

$C.Events.onStation({
    click : function(e){
        console.log(e)
            return false;
    },
    mouseenter : function(e){
        return false;
    },
    mouseleave : function(e){
        return false;
    }
})

That works fine. Everything's passed through, etc. Inside my $B.Events Object:

Events : new function(){
    var _station = function(obj){
        // delegate the events to the primary SVG node
        for(var type in obj){
            $(City.Map.node).delegate('g', type, function(){
            obj[type]()
        })
    }
    return {
        onStation : _station
    }
    // others taken out for relevance
}()

Now, with this, if I just pass in obj[type] instead of wrapping it in another function, it works fine. Only problem with that is I need to do some pre-work with the function being passed in (i.e. messing with the event data object) as well as moving all the return false's into the delegation code and not muck up my other file.

So how can I get the functions from the first code block executed within the callback handler function in jQuery's .delegate() function?

Edit in Response

I think it's a step in the right direction. I had a feeling it had something to due with the nature of JS and not necessarily the logic. It's why I hate Javascript sometimes.

The problem with this solution is it's passing a primitive to a generic builder function. I need to store and return an executable function. The few things I've tried have been unsuccessful. Here's an example of the many things I tried:

var _station = function(events){
    var _funcs = {}
    var _selection = null;

    var create = function(f){
        return function(){ return f() }
    }
    for(var t in events){
        _funcs[t] = create(t, events[t])
    }
    console.log(_funcs)

    // delegate the events to the primary SVG node
    for(var type in events){
        $('#stations', Bart.Map.node).delegate('g', type, function(e){                
            _funcs[type](e)
            e.stopPropagation()
        })
    }
}

When I log(_funcs[type]) it comes back as a function, but I can't execute it for the life of me.

This closure stuff kills me.

Phix
  • 9,364
  • 4
  • 35
  • 62
  • 1
    I'm not quite sure but I assume your problem is that you are creating a closure in a loop. Please have a look at [this question](http://stackoverflow.com/questions/750486/javascript-closure-inside-loops-simple-practical-example) and let us know whether this fixes it. – Felix Kling Jan 10 '12 at 10:10
  • Yes, I think it's something to do with that, but I can't get the code adapted to my uses. I updated the original post to reflect. Thanks Felix, gonna bookmark that one for future use. – Phix Jan 10 '12 at 19:40

1 Answers1

2

You still have the problem with generating a closure an a loop. You can pass type as event data:

var $target = $('#stations', Bart.Map.node); // capturing is a good idea

for(var type in events){
    $target.on(type, 'g', {type: type}, function(e){                
        _funcs[e.data.type](e);
        e.stopPropagation();
    })
}

Or you can iterate over events with jQuery.each:

$.each(events, function(type) {
    $target.on(type, 'g', function(e){                
        _funcs[type](e);
        e.stopPropagation();
    });
});

The important point is that every closure (event handler) has access to it's own type variable.

Note that I used .on() instead of .delegate(), as preferred since jQuery 1.7.

Felix Kling
  • 795,719
  • 175
  • 1,089
  • 1,143
  • You beat me to it! I revisited the `on()` method and it seems to work great. Thank you very much for putting in the time. Cheers! – Phix Jan 10 '12 at 20:18
  • @FelixKling, Do you know a way to delegate event on SVG elements? – Starx Jan 21 '13 at 04:01