views:

141

answers:

3

I have a jQuery function with basically makes an entire table row clickable, but copying a link and duplicating the link in each child cell in the row. In my projects, some of the links may have onclick javascript events, so I need my function to be able to copy those events as well, but I am having trouble doing that.

Here's my current function:

jQuery.fn.linker = function(selector) {
    $(this).each(function() {
        var from = $(selector, this);
        if (from.length > 0) {
            var href = from.attr('href');
            if (href) {
                var link = $('<a href="' + $(selector, this).attr('href') + '"></a>').css({
                    'text-decoration': 'none',
                    'display': 'block',
                    'padding': '0px',
                    'cursor': 'pointer',
                    'color': $(this).css('color')
                });

                $(this).children()
                //.css('padding', '0')
               .wrapInner(link);
            }
        }
    });
};

I've tried different methods to copy events but can't seem to get it to work:

1) from[0].events is always undefined:

if (from.size() && from[0].events && link.size()) {

    var events = from[0].events;
    link.each(function() {
        for (var type in events) {
            for (var handler in events[type]) {
                jQuery.event.add(this, type, events[type][handler], events[type][handler].data);
            }
        }
    });
}

2) This one seems to execute ok, but clicking on the copied links doesn't do anything

link.attr('onclick',from.attr('onclick'));
A: 

for the event handlers to carry on existing on the elements. you can not use

$('bla').click...or anything that implements it like that

Instead you have to use one of the following methods:

$('bla').live('click', function(){...});

or

$("table").delegate("tr", "click", function(){
    .....
});

The difference between live and delegate is that delegate can easily exist within a chain. as oppose to live. delegate is a new feature.

for single elements in the case of using the clone() function, you need to pass in a true parameter in clone to keep the original event handler. this is not your case here but it is useful to know.

$('.bla').clone(true).appendTo('body or something');
XGreen
+1  A: 

As of jQuery 1.4, you can do this with .clone() it now has a .clone(true) overload.

This instructs it to copy data and events over (events are held in .data('events')).

Your link creation can be like this:

            var link = from.clone(true).css({
                'text-decoration': 'none',
                'display': 'block',
                'padding': '0px',
                'cursor': 'pointer',
                'color': $(this).css('color')
            });
Nick Craver
A: 

You can rebind the events after copying. But the new clone is much better.

naugtur
How is that relevant? ;)
mway
Yeah, it wasn't. I must have been not fully conscious while writing...
naugtur