19

Whenever I use ajax to dynamically create new content, .clone(), append() etc, the new element looses any triggers and events I programmed =(

After making copy, simple things that WORK on other elements like adding a class to , on the copied elements no longer work. Any new ajax content does not work. Command buttons no longer work. What can I do?

I am cloning this HTML, and the command buttons no longer work. Styling the span elements no longer work on the CLONED elements:

<div name="shows" id="x"><br/> <!-- The ID depends on the database-->
    <div name="shows" id="x">
        ID: <input disabled="disabled" size="7" value="x" name="id" />
        Status: 
        <select name="status" >
          <option selected="selected" >Display</option>
          <option >Hide</option>
        </select>
        <br/><br/>
        <span class="required" id="date_txt">*Date: </span><input type="text" value="" name="date" />
        &nbsp;&nbsp;
        <span class="required" id="title_txt">*Title: </span><input type="text" size="65" value="" name="title" />
        <br/>
        <span class="required" id="venue_txt">*Venue: </span><input type="text" size="45" value="" name="venue" />
        Telephone: <input type="text" value="" name="tel" />
        <br/>
        URL: <input type="text" size="100" value="" name="url" />
        <br/><br/>
        Address: <input type="text" size="45" value="" name="address" />
        &nbsp;&nbsp;
        <span class="required" id="city_txt">*City: </span><input type="text" value="" name="city" />
        <br/>
        State: <input type="text" value="" name="state" />
        ZIP: <input type="text" value="" name="zip" />
        <span id="country_txt">*Country: </span><input type="text" value="United States" name="country" />
        <br/>
        <br/>Comments: <br/>
        <textarea cols="80" rows="8" name="comments" ></textarea>
    </div>
    <!-- START OF:commands  -->
    <div id="commands" >
        <button name="edit" id="edit" >Edit</button> 
        <button name="delete" id="delete" >Delete</button>
    <br />
    <hr />
    <br />
    </div>
    <!-- END OF:commands  -->
</div>
<!-- END OF:new -->

New comments added, 11/03/2011:

OK, I figured out the problem and I had an error on my jQuery. Now, when I add .clone( true ) ALMOST everything works.


My new problem is the UI datepicker. After cloning the HTML, when I click on the newly cloned date field, the focus goes to the (old) datefield the data was cloned from. More over, if I select a date, the value goes to the old datefield -Not the newly cloned datefield.

Here is my ajax code (After a successful submition):

UI datepicker code:

$("input[name='date']").datepicker({ dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true, numberOfMonths: 3, showButtonPanel: true});

Ajax:

    ...ajax code...
function(data)
{
var $msg = eval(data);
if( $msg[0] == 1 )
    {
    //#var.new
        $id = '#'+$msg[1];
        $data = $("#new");
    $new = $data.clone(true);
    $new.find('input.datefield').datepicker();


        $new.attr("id", $id);
        $new.children('[name="id"]').val($id);
        $new.children('[name="id"]').attr("value", $id);
        $new.children(":input").each(function() { var $value = $(this).val(); $(this).attr("value", $value); });
        $new.prepend( "<br/>" );

        $commands = $("#blank").children("#commands").clone(true);
        $commands.children("#add").text("Update");
        $commands.children("#add").attr("pk", $id);
        $commands.children("#add").attr("name", "update");
        $commands.children("#add").attr("id", "update");

        $commands.children("#reset").text("Delete");
        $commands.children("#reset").attr("pk", $id);
        $commands.children("#reset").attr("name", "delete");
        $commands.children("#reset").attr("id", "delete");

        $new.append( $commands );

        //#animation
        //blank.slideUp
        $("#blank").slideUp(2500, function(){
        $("#ADDNEW").html("&#9658; New:");
        //$("#blank").clone().prependTo( $("#active") );
        //$("#blank").prependTo( "#active" );

        //active.slideUp
        $("#active").slideUp("slow", function(){
        $("#ON").html("&#9658; Active:");
        $("#active").prepend( $new );
        $('#reset').trigger('click');

        //active.slideDown
        $("#active").slideDown(8500, function(){
        $("#ON").html("&#9660; Active:");

        //blank.slideDown
        $("#blank").slideDown(3500, function(){
        $("#ADDNEW").html("&#9660; New:");
        load_bar(0);

        }); //end: anumation.#blank.slideDown
        }); //end: anumation.#active.slideDown
        }); //end: anumation.#blank.slideUp
        }); //end: anumation.#active.slideUp

        //$("#new").fadeOut(2000, function(){
        //START: blank
        //alert( $("#blank").html() );
        //$dad = $("#new");
        //$dad.children('input[name!="id"][name!="country"], textarea').val('');
        //$dad.children('[name="country"]').val("United States");
        //$dad.children('[name="date"]').focus();
        //END: blank
        //$("#new").fadeIn(2000, function(){
        //alert( $msg );
        //}); //end: anumation.fadeIn
        //}); //end: anumation.fadeOut
        } //end: if
    else
        {
        //var varMSG = data;
        //alert( "Hello" );
        alert( $msg );

        //$("#add").attr("disabled", false);
        //$("#reset").attr("disabled", false);
        load_bar(0);
        } //end: if.else
    }//end: $.post.function
); //END:$.post
}); 
//END:ajax
Omar
  • 11,783
  • 21
  • 84
  • 114
  • 1
    Can you post some sample javascript? – rossipedia Nov 03 '11 at 01:31
  • Does the HTML above _replace_ content that was already on the page, or _add_ to it? Because any JS that uses element IDs is not going to work properly if you are adding additional copies with the same IDs (e.g., `id="edit"` on your button). Please show your JS. – nnnnnn Nov 03 '11 at 01:39
  • What does "no longer work" mean? – RobG Nov 03 '11 at 01:56

4 Answers4

50

.clone( true ) does the trick.

Documentation: http://api.jquery.com/clone/

Šime Vidas
  • 182,163
  • 62
  • 281
  • 385
  • I used .clone( true ) but it still does not work. span elements are supposed to change color (toggle class .required) depending on the input's change. Yet, but they do not. – Omar Nov 03 '11 at 01:27
  • @Omar Could you post the JavaScript code that clones and appends those elements? – Šime Vidas Nov 03 '11 at 01:34
  • 1
    By the sound of his question it looks like he should have gone for `clone(true, true)` instead. – hugomg Nov 03 '11 at 01:56
  • 2
    @missingno `true` twice is not needed, since the value of the second parameter matches the value of the first argument by default... – Šime Vidas Nov 03 '11 at 02:31
1

Hi I'm having a bit similar use case, I have some dynamically generated content that contains a button, click event is responding to the original button but not the generated one, I've done before :

$('.someclass').on('click', function() {

but i resolved my problem by replacing the on by live like this :

$('.someclass').live('click', function() {
krachleur
  • 356
  • 3
  • 14
0

If your handlers are setup using something like $('.class').click( ... )

Try something like this instead: $('.class').live('click', ...)

Live applies to elements with the class that may not exist yet.

Cory Kendall
  • 7,195
  • 8
  • 37
  • 64
0

I finally got the UI datepicker to work properly. I had to completely remove datepicker BEFORE cloning and add it AFTER cloning elements. The guys at UI should make it easier for us. Go figure!

Just before cloning:

//#datepicker
$("input[name='date']").datepicker( "destroy" );
$("input[name='date']").removeClass("hasDatepicker").removeAttr('id');

After cloning:

$("input[name='date']").datepicker({ dateFormat: 'yy-mm-dd', changeMonth: true, changeYear: true, numberOfMonths: 3, showButtonPanel: true});
Omar
  • 11,783
  • 21
  • 84
  • 114