0

I'm generating some HTML at runtime and I'm wondering how to make a plugin work on the newly created HTML. I've got something that looks llike this:

<input type="text" class="SomeClass">
<div id="Test"></div>

<script>

    function Start() {

        setTimeout(function () {

            $('#Test').html('<input type="text" class="SomeClass">');

        }, 1000);       
    }

    $(".SomeClass").SomePlugin();

    $(Start);

</script>

The input element has all the functionalities of the plugin but when I add the HTML inside the Test div the input element inside there doesn't work as expected. How can I use the plugin on dynamically generated HTML?

halfer
  • 19,824
  • 17
  • 99
  • 186
frenchie
  • 51,731
  • 109
  • 304
  • 510

2 Answers2

1

For plugin to work with new created elements, you need to init the plugin on those elements for it to work. There are several ways to do this, such as calling it again when new elements are added.

If you just want to avoid changing your code and adding that, you could override jquery html to check if you are adding an element with SomeClass and call the plugin for it automatically:

(function($)
{
    var oldhtml = $.fn.html; //store old function
    $.fn.html = function() //override html function
    {
        var ret = oldhtml.apply(this, arguments); // apply jquery html
        if(arguments.length){
            if(ret.find(".SomeClass").length){
                ret.find(".SomeClass").SomePlugin(); // call plugin if the html included an element with .SomeClass
            }
        }
        return ret;
    };
})(jQuery);




    $.fn.SomePlugin = function() {
      $("body").append("plugin activated <br/>");
    }

    function Start() {

      setTimeout(function() {

        $('#Test').html('<input type="text" class="SomeClass">');
        $('#Test').html()

      }, 1000);
    }

    $(".SomeClass").SomePlugin();

    $(Start);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="text" class="SomeClass">
<div id="Test"></div>
juvian
  • 15,875
  • 2
  • 37
  • 38
  • You answer works brilliantly! I would add one HUGE HUGE modification!! If at some point in the code you call .html() with no arguments, it will bug. So you need to add a condition to test if there are arguments, like this: if (arguments.length && ret.find('.SomeClass').length) instead of just if(ret.find(".SomeClass").length) – frenchie Mar 26 '15 at 00:15
0

I opted for a solution that used jQuery promises. Here is the Fiddle

The HTML (basic copy of yours):

<input type="text" class="SomeClass">
<div id="Test"></div>

The Javascript:

$.fn.SomePlugin = function(){
    $(this).val("plugin activated");
}

function Start() {

    alert('hi from start');
         $('#Test').html('<input type="text" class="SomeClass">');

    return $.when();
}

$(document).ready(function(){  
    Start().then(function () {
        alert('hi from done');
        $(".SomeClass").SomePlugin();
    });
});

I had some issue with the $(Start) so i opted for the document.ready approach. The only real difference is that Start returns $.when (SO Post Here) and I chain a 'then' after the call to start. This allows the page to setup and then you can run any plugins that you want and ensure that the required elements are in the DOM before the plugin attempts to manipulate them.

Community
  • 1
  • 1
JasonWilczak
  • 2,303
  • 2
  • 21
  • 37