Praful Bagai
Praful Bagai

Reputation: 17392

How to load a apply jQuery function upon appending a <div> via Ajax?

I'm appending a <div> via Ajax. There are jQuery functions and CSS to be applied to that <div> after getting appended dynamically via Ajax. The <div> gets appended correctly but the jQuery functions and CSS does not get loads for that <div>. How do I do it?

AJAX CODE

$.ajax({
            type: "POST",
            url: "/dashboard/",
            data : { 'widgets_list' : widgets_list },
            success: function(result){
                console.log(widgets_list);
                $("#column1").append(result);     // div gets appended.
                }
            });

view.py

HTMLstr += "<div class='portlet'><div class='portlet-header'>Live Graph</div>" + \
                    "<div class='portlet-content' id='live_graph' style='height: 270px  margin: 0 auto'>" + \
                    "</div></div>"

return HttpResponse(HTMLstr)            

The jQuery functions which needed to applies are:-

 $(function() {
    $( ".column" ).sortable({
      connectWith: ".column",
      handle: ".portlet-header"
    });

    $( ".portlet" ).addClass( "ui-widget ui-widget-content ui-helper-clearfix ui-corner-all" )
      .find( ".portlet-header" )
        .addClass( "ui-widget-header ui-corner-all" )
        .prepend( "<span class='ui-icon ui-icon-minusthick'></span>")
        .end()
      .find( ".portlet-content" );

    $( ".portlet-header .ui-icon" ).click(function() {
      $( this ).toggleClass( "ui-icon-minusthick" ).toggleClass( "ui-icon-plusthick" );
      $( this ).parents( ".portlet:first" ).find( ".portlet-content" ).toggle();
    });

 });

and 1 more jQuery function.

CSS

<style>
              body { min-width: 520px; }
              .column { width: 170px; float: left; padding-bottom: 100px;}
              .portlet { margin: 0 1em 1em 0; }
              .portlet-header { margin: 0.3em; padding-bottom: 4px; padding-left: 0.2em; }
              .portlet-header .ui-icon { float: right; }
              .portlet-content { padding: 0.4em; max-height: 270px;}
              .ui-sortable-placeholder { border: 1px dotted black; visibility: visible !important; height: 50px !important; }
              .ui-sortable-placeholder * { visibility: hidden; }
</style>

UPDATED QUESTION

HTML

<div class="column span4" id="column1">
                <div class="portlet">
                    <div class="portlet-header">Line Chart</div>
                    <div class="portlet-content" id="basic_line" style="height: 270px"></div>
                </div>
</div>

jQuery Function

$(function () { // I replaced this line with $("#portlet").on('click', '#live_graph',function() {.... But it didnt work!!
    $(document).ready(function() {
        Highcharts.setOptions({
            global: {
                useUTC: false
            }
        });

        var chart;
        $('#live_graph').highcharts({
            chart: {
                type: 'spline',
                animation: Highcharts.svg, // don't animate in old IE
                marginRight: 10,
                events: {
                    load: function() {

                        // set up the updating of the chart each second
                        var series = this.series[0];
                        setInterval(function() {
                            var x = (new Date()).getTime(), // current time
                                y = Math.random();
                            series.addPoint([x, y], true, true);
                        }, 1000);
                    }
                }
            },
            title: {
                text: 'Live random data'
            },
            xAxis: {
                type: 'datetime',
                tickPixelInterval: 150
            },
            yAxis: {
                title: {
                    text: 'Value'
                },
                plotLines: [{
                    value: 0,
                    width: 1,
                    color: '#808080'
                }]
            },
            tooltip: {
                formatter: function() {
                        return '<b>'+ this.series.name +'</b><br/>'+
                        Highcharts.dateFormat('%Y-%m-%d %H:%M:%S', this.x) +'<br/>'+
                        Highcharts.numberFormat(this.y, 2);
                }
            },
            legend: {
                enabled: false
            },
            exporting: {
                enabled: false
            },
            series: [{
                name: 'Random data',
                data: (function() {
                    // generate an array of random data
                    var data = [],
                        time = (new Date()).getTime(),
                        i;

                    for (i = -19; i <= 0; i++) {
                        data.push({
                            x: time + i * 1000,
                            y: Math.random()
                        });
                    }
                    return data;
                })()
            }]
        });
    });

});

I want this highchart to be in the portlet-content, but I'm unable to. Where am I going wrong?

.on( events [, selector ] [, data ], handler(eventObject) )

Can ready be an event?

Upvotes: 0

Views: 572

Answers (1)

AnthonyS
AnthonyS

Reputation: 2469

I'm going to break it down by the functions you listed.

Function 1

$( ".column" ).sortable({
     connectWith: ".column",
     handle: ".portlet-header"
 });

This is very specific to jQueryUI, but in order for Function 1 to work, you need to use http://api.jqueryui.com/sortable/#method-refresh . Since some of the items in your sortable are loaded later you need to referesh the sortable to recognize these items.

So you will have code like

success: function(result){
   // div gets appended.
   $("#column1").append(result);     
    // refresh sortable items now that markup is appended to columns
   $( ".column ).sortable( "refresh" );
}

Function 2

   $( ".portlet" ).addClass( "ui-widget ui-widget-content ui-helper-clearfix ui-corner-all" )
      .find( ".portlet-header" )
        .addClass( "ui-widget-header ui-corner-all" )
        .prepend( "<span class='ui-icon ui-icon-minusthick'></span>")
        .end()
      .find( ".portlet-content" );

Is there a reason why this markup is not generated in view.py , since view.py is already generating dynamic markup. If you prefer to do this in jQuery, make you sure you invoke the function after appending the result.

Function 3

   $( ".portlet-header .ui-icon" ).click(function() {
      $( this ).toggleClass( "ui-icon-minusthick" ).toggleClass( "ui-icon-plusthick" );
      $( this ).parents( ".portlet:first" ).find( ".portlet-content" ).toggle();
    });

Instead of needing to call this function each time the element is created, there is a concept known as event delegation. The premise of event delegation is that Delegated events have the advantage that they can process events from descendant elements that are added to the document at a later time. But in order to apply event delegation, Event handlers are bound only to the currently selected elements; they must exist on the page at the time your code makes the call to* From your ajax call it looks like the function is "#column_1" already exists by the time the result is appended.

An example of event delegation is :

  // This tells #column_1 that if a descendant element matches the selector
  // '.portlet-header .ui-icon' then invoke the function

  $('#column_1').on('click', '.portlet-header .ui-icon' ).,function() {
      $( this ).toggleClass( "ui-icon-minusthick" ).toggleClass( "ui-icon-plusthick" );
      $( this ).parents( ".portlet:first" ).find( ".portlet-content" ).toggle();
    });

Upvotes: 4

Related Questions