简体   繁体   中英

DataTables Pipelining and FixedColumns

I currently have a DataTable that uses pipelining and I now need it to also use FixedColumns. I can do it in the browser console okay but getting it to work automatically after loading, I am at a loss.

What I have in fnInitComplete:

var someObj = new FixedColumns(oTable, {
                                    "iLeftColumns": 6,
                                    "iLeftWidth": 600
                                  });

though this seems to reload the table or something because fnDrawCallback and fnRowCallback is called quite a bit after this.

EDIT: This is the closest example I can find, however, it does not use pipelining. http://datatables.net/release-datatables/extras/FixedColumns/server-side-processing.html

I've put simple working example together. Placing the FixedColumns initialization code into fnInitComplete was enough to make it work:

var oTable = $('#example').dataTable( {
    // ...
    ,"sScrollX": "100%"
    ,"sScrollXInner": "150%"
    ,"fnInitComplete": function () {
        var someObj = new FixedColumns(oTable, {
                    "iLeftColumns": 1,
                    "iLeftWidth": 50
        });
    }
} );

I have constructed an example using the pipe-lining example from datatables and adding the FixedColumns code. I referenced their server side PHP script, and solved the XSS problem by PHP GET proxy . The full test example code is here (you can paste it to your own file):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd">
<html>
    <head>
        <!--<base href="http://datatables.net/examples/server_side/"> -->
        <meta http-equiv="content-type" content="text/html; charset=utf-8" />
        <link rel="shortcut icon" type="image/ico" href="http://www.sprymedia.co.uk/media/images/favicon.ico" />

        <title>DataTables example</title>
        <style type="text/css" title="currentStyle">
            @import "http://datatables.net/release-datatables/media/css/demo_page.css";
            @import "http://datatables.net/release-datatables/media/css/demo_table.css";
        </style>
        <script type="text/javascript" language="javascript" src="http://datatables.net/release-datatables/media/js/jquery.js"></script>
        <script type="text/javascript" language="javascript" src="http://datatables.net/release-datatables/media/js/jquery.dataTables.js"></script>
        <script type="text/javascript" charset="utf-8" src="http://datatables.net/release-datatables/extras/FixedColumns/media/js/FixedColumns.js"></script>
        <script type="text/javascript" charset="utf-8">


var oCache = {
    iCacheLower: -1
};

function fnSetKey( aoData, sKey, mValue )
{
    for ( var i=0, iLen=aoData.length ; i<iLen ; i++ )
    {
        if ( aoData[i].name == sKey )
        {
            aoData[i].value = mValue;
        }
    }
}

function fnGetKey( aoData, sKey )
{
    for ( var i=0, iLen=aoData.length ; i<iLen ; i++ )
    {
        if ( aoData[i].name == sKey )
        {
            return aoData[i].value;
        }
    }
    return null;
}

var hadSomeData = false;

function fnDataTablesPipeline ( sSource, aoData, fnCallback ) {
    var iPipe = 5; /* Ajust the pipe size */

    var bNeedServer = false;
    var sEcho = fnGetKey(aoData, "sEcho");
    var iRequestStart = fnGetKey(aoData, "iDisplayStart");
    var iRequestLength = fnGetKey(aoData, "iDisplayLength");
    var iRequestEnd = iRequestStart + iRequestLength;
    oCache.iDisplayStart = iRequestStart;

    console.log('pipeline called');
    /* outside pipeline? */
    if ( oCache.iCacheLower < 0 || iRequestStart < oCache.iCacheLower || iRequestEnd > oCache.iCacheUpper )
    {
        bNeedServer = true;
    }

    /* sorting etc changed? */
    if ( oCache.lastRequest && !bNeedServer )
    {
        for( var i=0, iLen=aoData.length ; i<iLen ; i++ )
        {
            if ( aoData[i].name != "iDisplayStart" && aoData[i].name != "iDisplayLength" && aoData[i].name != "sEcho" )
            {
                if ( aoData[i].value != oCache.lastRequest[i].value )
                {
                    bNeedServer = true;
                    break;
                }
            }
        }
    }

    /* Store the request for checking next time around */
    oCache.lastRequest = aoData.slice();

    if ( bNeedServer )
    {
        if ( iRequestStart < oCache.iCacheLower )
        {
            iRequestStart = iRequestStart - (iRequestLength*(iPipe-1));
            if ( iRequestStart < 0 )
            {
                iRequestStart = 0;
            }
        }

        oCache.iCacheLower = iRequestStart;
        oCache.iCacheUpper = iRequestStart + (iRequestLength * iPipe);
        oCache.iDisplayLength = fnGetKey( aoData, "iDisplayLength" );
        fnSetKey( aoData, "iDisplayStart", iRequestStart );
        fnSetKey( aoData, "iDisplayLength", iRequestLength*iPipe );
        console.log('actually asking server!');

        $.getJSON( sSource, aoData, function (json) { 
            /* Callback processing */
            console.log('got back!');
            oCache.lastJson = jQuery.extend(true, {}, json);

            if ( oCache.iCacheLower != oCache.iDisplayStart )
            {
                json.aaData.splice( 0, oCache.iDisplayStart-oCache.iCacheLower );
            }
            json.aaData.splice( oCache.iDisplayLength, json.aaData.length );

            console.log('have data 2! ' + json.aaData.length);
            hadSomeData = true;
            fnCallback(json);
            console.log('after callback');
        } );
    }
    else
    {
        json = jQuery.extend(true, {}, oCache.lastJson);
        json.sEcho = sEcho; /* Update the echo for each response */
        console.log('have data! ' + json.aaData.length);
        json.aaData.splice( 0, iRequestStart-oCache.iCacheLower );
        json.aaData.splice( iRequestLength, json.aaData.length );
        hadSomeData = true;
        fnCallback(json);
        return;
    }

}

$(document).ready(function() {

var fixedColDone = false;

    var oTable = $('#example').dataTable( {
        "bProcessing": true,
        "bServerSide": true,
//      "sAjaxSource": "http://datatables.net/examples/examples_support/server_processing.php",
        "sAjaxSource": "get_proxy.php",
        "fnServerData": fnDataTablesPipeline
        ,"sScrollX": "100%"
        ,"sScrollXInner": "150%"
/*  ,"fnDrawCallback": function () {
        console.log('draw callback');
        if (!fixedColDone && hadSomeData) {
            console.log('actually drawing!');
            var someObj = new FixedColumns(oTable, {
                                    "iLeftColumns": 1,
                                    "iLeftWidth": 50
                                  });       
            fixedColDone = true;
        }
    }*/
    ,"fnInitComplete": function () {
            var someObj = new FixedColumns(oTable, {
                                    "iLeftColumns": 1,
                                    "iLeftWidth": 50
                                  });       
    }
    } );


/*setTimeout(function () {
}, 5000);*/

} );
</script>
    </head>
    <body id="dt_example">
        <div id="container">
            <div class="full_width big">
                <i>DataTables</i> server-side processing with pipelining example
            </div>

            <h1>Preamble</h1>
            <p>When using server-side processing with DataTables, it can be quite intensive on your server having an Ajax call every time the user performs some kind of interaction - you can effectively DDOS your server with your own application!</p>
            <p>This example shows how you might over-come this by modifying the request set to the server to retrieve more information than is actually required for a single page's display. This means that the user can page multiple times (5 times the display size is the default) before a request must be made of the server. Paging is typically the most common interaction performed with a DataTable, so this can be most beneficial to your server's resource usage. Of course the pipeline must be cleared for interactions other than paging (sorting, filtering etc), but that's the trade off that can be made (sending extra information is cheep - while another XHR is expensive).</p>

            <h1>Live example</h1>
            <div id="dynamic">
<table cellpadding="0" cellspacing="0" border="0" class="display" id="example" style="width: 200px;">
    <thead>
        <tr>
            <th width="20%">Rendering engine</th>
            <th width="25%">Browser</th>
            <th width="25%">Platform(s)</th>
            <th width="15%">Engine version</th>
            <th width="15%">CSS grade</th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td colspan="5" class="dataTables_empty">Loading data from server</td>
        </tr>
    </tbody>
    <tfoot>
        <tr>
            <th>Rendering engine</th>
            <th>Browser</th>
            <th>Platform(s)</th>
            <th>Engine version</th>
            <th>CSS grade</th>
        </tr>
    </tfoot>
</table>
</body>
</html>

And the get_proxy.php (you have to save it into the same directory), derived from https://stackoverflow.com/a/18800645/684229

<?php

$url = 'http://datatables.net/examples/examples_support/server_processing.php'; //Edit your target here

//open connection
$ch = curl_init();

//set the url, number of POST vars, POST data
curl_setopt($ch,CURLOPT_URL, $url . "?" . $_SERVER['QUERY_STRING']);

//execute post
$result = curl_exec($ch);

//close connection
curl_close($ch);

?>

EDIT: Try to put the initialization like here (remove it from other places):

setTimeout(function () {
    var someObj = new FixedColumns(oTable, {
                "iLeftColumns": 1,
                "iLeftWidth": 50
    });
}, 10000);

and wait 10 seconds. Is it displayed correctly now?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM