1

Javascript seems to be disabled in all jQuery UI tabs that are loaded through ajax. I am testing this with jQuery tooltips and .click() alerts. Javascript works fine in tabs that aren't loaded through ajax (IDs present on the page).

Here is how I am calling the tabs:

$(function() {
$('#foo-tabs').tabs(
{
heightStyle: 'content',
// Callback run when selecting a tab
beforeLoad: function(event, ui) {

// If the panel is already populated do nothing
if (ui.panel.children().size() > 0)
    return false;

//load specific ID within target page
ui.panel.load($('a', ui.tab).attr('href') + $('a', ui.tab).attr('data-target'));

// stop the default process (default ajax call should not be launched)
return false;
}
}
);
});

Here's the javascript I'm trying to activate:

$(function() {
$( '.activate-tooltip' ).tooltip();
});

And a test:

$(function() {
$("h1").click(function() {
alert("zomg javascript works!");
});
});

Any ideas on how to get javascript working in all ajax loaded tabs? Thank you for taking the time to go through this!

7
  • You could use live function of jquery to trigger click event for dynamically created html. $("h1").live("click", function(){ alert("zomg javascript works!"); }); Commented Dec 18, 2012 at 14:36
  • 1
    @vimalnath They could, but they shouldn't. The .live() function has been deprecated since jQuery 1.7 was released; they should use .on() (1.7+) or .delegate() in preference to .live(). The only time you should be writing new code using .live() is if you're using a version of jQuery prior to 1.4.3 (when .delegate() was added); and if that's the case you should probably upgrade. Commented Dec 18, 2012 at 14:39
  • Live has been deprecated. You could use $(document).on('click', 'h1', function(){});. Commented Dec 18, 2012 at 14:40
  • my bad, yes please use .on instead of .live Commented Dec 18, 2012 at 14:40
  • @AnthonyGrist .delegate is also not recommended as its been superseded by .on. Commented Dec 18, 2012 at 14:49

3 Answers 3

2

The problem is that at the time when your binding your events those elements are not present in the DOM. The way to deal with this is by delegating the events to a higher level DOM element (up to the Document if necessary) that does exist in the DOM.

For example to delegate using .on

$(document).on('click', 'h1', function() {
      alert("zomg javascript works!");
 });

For the tooltip plug in you can do something like the following

   $(function() {
        //initialize tooltip plugin
        //dvCont is just an existing element in the DOM, you can use #foo-tabs
        $('#dvCont').tooltip({
            items: '.activate-tooltip',
            content: function(){
                var element = $( this );
               if ( element.is( ".activate-tooltip" ) ) {
                return 'Some text';
                }
                if ( element.is( "[title]" ) ) {
                  return element.attr( "title" );
               }

             }
          });

      $('#dvCont').append($('<div class="activate-tooltip" >Test</div>')); //dynamic content

    });

Here's a link to a jsBin

You can see a more complete example on the Demo page for the plugin.

Edit:

In response to why you should use event delegation if you can just initialize the plugin right after you add it to the DOM, I think its worth pointing out that besides for handling dynamic content another reason to use event delegation is due to performance. That is with event delegation you are able to attach fewer event handlers which in turn means less memory used.

To illustrate here's a link to a jsPerf that compares using event delegation vs binding directly.

Sign up to request clarification or add additional context in comments.

6 Comments

Thank you! This works perfectly. Any idea on how I would get this to work for the jquery tooltips? Somehow $(document).on('.activate-tooltip', function() doesn't sound very right... Does this also mean that there is no way to activate all javascript for the ajax loaded tabs?
Did you take a look at the example I posted from the jQuery UI tooltips Demo page?
Yup - played around it but it still wasn't working. The solution is explained in Anthony's answer. But your post was very helpful - upvoted!
I updated my post with an example of how you can do it for the tooltip plugin,
Well with this code you are only binding one event handler (to the parent element), with the code Anthony posted you are binding it to every element with the .activate-tooltip class (the less event handlers bound the faster your page should be, it might not make that much of a difference for this particular case but in general thats the rule). Further if you add another element afterwards to your container afterwards with this code it will still get the tooltip with the Anthony's code it won't.
|
1

When you call a method such as .click(), it adds the event handler directly to all of the elements in the jQuery object (i.e. those that matched the selector at the time it was run). When you add new elements to the page they don't have the associated event handlers, because they didn't exist when that code was executed.

The solution is event delegation; the general principle is that you set the event handler on an element higher up the DOM tree - one that contains all of the elements you wish to match. Then, when an event of that type is triggered on an element inside it and bubbles up to the element with the handler, it checks to see if the triggering element meets the conditions; if it does, it executes the callback function.

However, this only works for event handlers, it won't work for plugins. I don't know of a way to delegate plugin initialisation, so you'll likely just have to execute the code again. Thankfully the .load() function takes a callback function which will run when the new tabs content has finished being loaded via AJAX.

ui.panel.load($('a', ui.tab).attr('href') + $('a', ui.tab).attr('data-target'), function() {
    $('.activate-tooltip', ui.panel).tooltip();
});

1 Comment

@AnthonyGrist Actually in this case (that is with the tooltip plugin) you initialize the plugin on a higher level element, not on the dynamically created content so it is doable. I posted an example in my post.Comments may only be edited for 5 minutes(click on this box to dismiss)
0

You could use on function of jquery to trigger click event for dynamically created html(in your case its the ajax function which creates dynamic html(tabs)). `

$("h1").on("click", function(){ alert("zomg javascript works!"); });

`

1 Comment

Just using $('h1') will only attach to the 'h1' elements that are on the page at load as opposed to after being loaded in dynamically.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.