tags:

views:

51

answers:

1

Hi there,

my actual problem is that .live() jQuery method is not working.

This si the code where i use it:

    jQuery.fn.sb_animateMenuItem = function()
    {
    var mousehoverColor = '#0089F7';
    var duration = 250;

    return this.each(function()
    {
        var originalColor = $(this).css('background-color');
        $(this).live('mouseover', function()
        {
            this.style.cursor = 'pointer';
            $(this).animate().stop();
            $(this).animate(
            {
                backgroundColor: mousehoverColor
            }, duration);
        });
        $(this).live('mouseout', function()
        {
            this.style.cursor = 'default';
            $(this).animate(
            {
                backgroundColor: originalColor
            }, duration);
        });
    });
};

This snipped is used i another page in this way:

<script type="text/javascript" src="ui/js/jquery-1.4.2.js"></script>
<script type="text/javascript" src="ui/js/jquery-ui-1.8.1.custom.min.js"></script>
<script type="text/javascript" src="ui/js/color.js"></script>
<script type="text/javascript" src="engine/js/tiny_mce/tiny_mce.js"></script>
<script type="text/javascript" src="ui/js/ui.js"></script>
<script type="text/javascript">
    // UI effects
    $(document).ready(function()
    {
      $('button').sb_animateButton();
      $('input').sb_animateInput();
      $('.top_menu_item').sb_animateMenuItem();
      $('.top_menu_item_right').sb_animateMenuItem();
      $('.left_menu_item').sb_animateMenuItem();
    });
</script>

Since my site uses AJAX requests i used the .live method in the first snippet, but when i load the page the effects are not applied the the button/input... tags.

If i remove the .live method and use the 'normal' way, ui effects defined in the first snipped are applied but only the the elements loaded before any AJAX request. The elements loaded after the ajax request are not affected by first snippet (though they have the same selector).

Thanks for helping.

+7  A: 

In short, you can't use .live() like this, it has to follow a selector base of some sort, this is from the .live() docs:

DOM traversal methods are not fully supported for finding elements to send to .live(). Rather, the .live() method should always be called directly after a selector, as in the example above.

You're calling .live() on a jQuery object representing a particular DOM element, instead you need to get the .selector the plugins running on, if there is one, this isn't guaranteed of course, then use that for .live, like this:

 jQuery.fn.sb_animateMenuItem = function() {
    $(this.selector).live(.....)

If you think about it, how does .live() work? It listens for event to bubble, checks if the target matches a selector, and executes if so (and in a context, that's a whole other discussion)...if you did $(DOMElement).live(), what selector is it checking to see if it should execute?

I guess you could argue based on the internal element uuid this should work, but then again that's just a .bind(), which would be less wasteful, so .live() doesn't do anything like that.


Update: Because I was curious about the easiest way to implement this without repeating code, here's a version of your plugin that chooses .live() or .bind() dynamically, based on if there is a selector present for .live() to use:

jQuery.fn.sb_animateMenuItem = function() {
  var mousehoverColor = '#0089F7';
  var duration = 250;
  var method = this.selector ? jQuery.fn.live : jQuery.fn.bind;
  method.apply(this, ['mouseover', function() {
     if(!jQuery.data(this, 'oColor'))
         jQuery.data(this, 'oColor', jQuery(this).css('background-color'));
     jQuery(this).stop(true).animate({ backgroundColor:mousehoverColor }, duration);
  }]);
  method.apply(this, ['mouseout', function() {
    jQuery(this).animate({ backgroundColor:jQuery.data(this, 'oColor') }, duration);
  }]);
  return this.css('cursor', 'pointer');
};

You can view a working demo showing both here.

Nick Craver
A really big +1. Learned a lot from this answer. +1 to OP as well for asking the question.
patrick dw
Well... i tried both ways, but it keeps not working. I decided to face the problem in another way: http://stackoverflow.com/questions/3032767/insert-html-into-a-page-with-ajax .
Silvio Iannone
@Silvio - What's not working? I provided a demo showing that this works, you should explain *what* isn't working. It's hard to give a solution when you don't know the problem...
Nick Craver
@Nick - I tried implementing your way, but it seems not working with my site. I copied and pasted it into the function, but what i get is just a non working effect. It's like if there is no effect.
Silvio Iannone
@Silvio - Do you have a link? You have something *else* outside this question affecting it. There are other functions you're calling for example, that aren't here.
Nick Craver
I still cant figure out what's the problem. However i solved it by re-applying ui effect to the elements loaded by the ajax function.
Silvio Iannone
@Silvio - What "ui-effect"? Are we discussing the function in the question/answer or something else entirely?
Nick Craver
@Nick - We're still discussing the function. I mean i found another way:This is how effects are applied when the page loads:$('button').sb_animateButton();$('input').sb_animateInput(); etc...So, when i load html content into the page i re-apply the ui effects by calling again:$('button').sb_animateButton();$('input').sb_animateInput();... and also the new elements like input boxes and buttons that are placed into the page by the ajax function gain ui-effects.Thanks again for helping. I'll try to implement your way in my site. It can be considered as the solution.
Silvio Iannone