Search code examples
javascriptjqueryajaxtablesorter

jquery tablesorter - on ajax update I'm losing sorting functionality


I've seen a few questions like this but as far as I can see I am doing everything correctly, I am a bit stumped as to why this isn't working.

Here is my ajax call which is inside a click function. #result_area is the tbody of the table and as you can see I am replacing the content. The content is loading fine but i lose table sorting functionality. Strange thing is, I'm sure this used to work so i am a bit perplexed as to what has changed. I have checked in firebug and the trigger update is definitely being called.

Update

I am getting the following error when $("#result_table").trigger("update"); is called:

Error: TypeError: parsers[i] is undefined
Source File: http://swishprint.dev/assets/js/common/jquery.tablesorter.js
Line: 483

Line 483 refers to the following:

function getCachedSortType(parsers,i) {
return parsers[i].type;
}; 

table initialisation function (called in doc ready):

    function table_init() {
        $('#result_table').tablesorter({
        widgets: ['zebra'],
        widgetZebra: {
            css: ["dark", "darker"]
        },
        headers: {
            0: {
            sorter: false
            },
            5: {
            sorter: false
            },
            7: {
            sorter: false
            },
            8: {
            sorter: false
            }
          }
       });
}

click function:

    function leftsort_click(event) { //main sort click (left menu)

    //build url and other unrelated stuff
            var page = window.name,
            page_index, api = $('#right_pane').jScrollPane({
                showArrows: true,
                maintainPosition: false
            }).data('jsp');   
            if (!$(this).hasClass('sort_cat')) {        
            $('ul.sort_ul li, ul.cat_items li').removeClass('active');
            $(this).addClass('active');
            var sid = $(this).attr('id');
            var title = $(this).html();
            var loadUrlx = page;
            if ((sid != '') && (sid != 'undefined')) {
                loadUrlx += '/' + sid;
            }
            var loadUrlStub = loadUrlx;
            if ($('.rpp_btn.active').length >= 1) {
                var res_per_page = $.trim($('.rpp_btn.active').html());
                page_index = $.trim($('.res_page_select.active a').html());
                if (($('.rpp_btn.active').hasClass('just_clicked')) || (!$('.res_page_select').hasClass('just_clicked'))) {
                page_index = '1';
                }
                if ((page_index != 1) || (res_per_page != 25)) {
                loadUrlx += '/' + page_index + '/' + res_per_page;
                }
                $('.rpp_btn, .res_page_select').removeClass('just_clicked');
            }       
            loadUrlx = b_url + loadUrlx;
            if (History.enabled) {
                History.pushState(null, null, loadUrlx);
                //var hash=History.getHash(), rootUrl = History.getRootUrl(), State = History.getState(), url = State.url, relativeUrl = url.replace(rootUrl,'');
            }
//Ajax call            
              $.ajax({
                    cache: false,
                    url: loadUrlx,
                    success: function(result) {
                        $("#result_area").html(result);
                        if ((page != 'home') && (page != 'guides')) {
                            var count_ele = $('.hidden_rescount').length;

                            //get td width and set width of table headers
                            api.reinitialise();
                            tsizer();
                            $("#result_table").trigger("update");
                        }
                    }
            });
        }

call for click function (in doc ready):

$('#mainc').on("click", "ul.sort_ul li, ul.cat_items li", function(event) {
    leftsort_click.call(this);
    });
    }

My HTML

<table width="100%" class="result_table tablesorter scrollableFixedHeaderTable" id="result_table" style="">
    <thead id="t_header">
        <tr>
            <th class="border_apps th_first th_img no-sort" id="th_img">IMG</th>
            <th class="border_apps th_name header headerSortUp" id="th_name">NAME</th>
            <th class="border_apps th_cat header" id="th_cat">CAT</th>
            <th class="border_apps th_urate header" id="th_urate">RATING <small>(USER)</small></th>
            <th class="border_apps th_orate header" id="th_orate">RATING <small>(ODDBALL)</small></th>
            <th class="border_apps th_info no-sort" id="th_info">INFO</th>
            <th class="border_apps th_alert header" id="th_alert">W</th>            <th class="border_apps th_edit no-sort" id="th_edit">EDIT</th>            <th class="border_apps th_last th_link no-sort" id="th_link">LINK</th>
        </tr>
    </thead>
    <tbody id="result_area">
//results here

</tbody>
</table>

Any help greatly appreciated.


Solution

  • You need to account for dynamically loaded information (via Ajax) with jQuery's on() method, specifically event delegation. http://api.jquery.com/on/

    When you originally load the page all of your jQuery code is run against elements existing in the page at that time. jQuery / JavaScript is not aware of any changes to the DOM made by dynamically loaded content after that. Using the delegation method of on() you can bind to a container that exists on the page at the time that it loads. When dynamic content is added to the container any event triggered in the container bubbles up to the existing element and is then acted on properly.

    For example you could do something like this -

    $('#result_area').on('event', 'element_causing_event', function() {...
    

    In this case the element_causing_event will cause the event to bubble up to #result_area where it can then be handled.

    After checking the docs (http://tablesorter.com/docs/example-ajax.html) it seems that you can update the table to let the plugin know that data has been added -

    $('#result_table').trigger('update');
    

    This should allow normal sorting. Try calling it in the success callback of your AJAX request.