官术网_书友最值得收藏!

Creating a sortable paginated table

One of the most common tasks we encounter when creating websites is displaying lists and tables. Most techniques focus on server-side sorting, paging, and the rendering of data. Our solution will be completely on the client side, suitable for small to medium amounts of data. The main benefit of a client-side solution is speed; sorting and switching pages will be nearly instantaneous.

In this recipe, we're going to create a client-side, sortable paginated table.

Getting ready

We assume that a service provides the data in a JSON object, containing a data property that is an array of arrays:

{data:[["object1col1", "object1col2"], ["object2col1", "object2col2"],  …]}

In our example, we're going to display a list of people near us. Every person in the table will have their own ID number, name, age, distance from us, and transportation method.

We're going to display the distance in km, and would like to be able to sort the list of people by their last names.

As table display problems quickly grow beyond the original simple problem, we're not going to build our own solution. Instead, we're going to use the excellent jQuery DataTables plugin available at http://datatables.net/.

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

How to do it...

Let's write the HTML page, CSS style, and JavaScript code.

  1. First, we're going to create an HTML page containing an empty table. We're also going to add some CSS to import a basic DataTables style for the table. The stylesheets are normally available with the DataTables distribution. Our index.html file is as follows:
    <!DOCTYPE HTML>
    <html>
        <head>
            <title>Sortable paged table</title>
            <style type="text/css">
                @import "http://live.datatables.net/media/css/demo_page.css";
                @import "http://live.datatables.net/media/css/demo_table.css";
                #demo, #container {
                    width:700px;
                }
                #demo td {
                    padding: 0.2em 2em;
                }
                #demo_info {
                    width:690px;
                    height:auto;
                }
            </style>
        </head>
        <body>
            <div id="container">
                <table id="demo">
                    <thead>
                        <tr>
                            <th>Id</th><th>Name</th><th>Age</th><th>Distance</th><th>Transportation</th>
                        </tr>
                    </thead>
                    <tbody>
                    </tbody>
                </table>
            </div>
            <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.8.2/jquery.min.js"></script>
            <script type="text/javascript" src="http://datatables.net/download/build/jquery.dataTables.min.js"></script>
            <script type="text/javascript" src="example.js"></script>
        </body>
    </html>

    The example includes a link to the minified version of DataTables hosted on the official website.

    The DataTables plugin appends the pager and info elements below the table. Because of this, we need to wrap our table inside a container element.

  2. And the example.js file is as follows:
    (function() {
        $.extend($.fn.dataTableExt.oSort, {
            "lastname-sort-pre": function (a) {
                return a.split(' ').reverse().join(' ');
            },
            "lastname-sort-asc": function(a, b) { return a < b ? -1 : a > b ? 1 : 0; },
            "lastname-sort-desc": function(a, b) { return a > b ? -1 : a < b ? 1 : 0; },
            "unitnumber-pre": function(a) { return new Number(a.split(' ')[0]); },
            "unitnumber-asc": function(a, b) { return a - b; },
            "unitnumber-desc": function(a, b) { return b - a; }
        } )
        var fetchData = function(callback) {
            var data = [
                [1,'Louis Garland', 12, 32, 'Walking'],
                [2,'Misty Lamar',32, 42, 'Bus'],
                [3,'Steve Ernest',32, 12, 'Cycling'],
                [4,'Marcia Reinhart',42, 180, 'Bus'],
                [5,'Lydia Rouse',35, 31, 'Driving'],
                [6,'Sean Kasten',80,42, 'Driving'],
                [7,'Patrick Sharkey',65,43, 'Cycling'],
                [8,'Becky Rashid',63, 51, 'Bus'],
                [9,'Michael Fort',34, 23, 'Walking'],
                [10,'Genevieve Blaine',55, 11, 'Walking'],
                [11,'Victoria Fry',58, 14, 'Walking'],
                [12,'Donald Mcgary',34, 15, 'Cycling'],
                [13,'Daniel Dreher',16, 23, 'Walking'],
                [14,'Valerie Santacruz',43, 35, 'Driving'],
                [15,'Jodi Bee',23, 13, 'Walking'],
                [16,'Jo Montana',14, 31, 'Cycling'],
                [17,'Stephanie Keegan',53, 24, 'Driving'],
                [18,'Philip Dewey',12, 29, 'Cycling'],
                [19,'Jack Clemons',11, 44, 'Walking'],
                [20,'Steve Serna',14, 60, 'Cycling']
            ];
            callback({data:data});
        };
        window.myTable = {};
        var table = window.myTable.table = $("#demo").dataTable({
            'bLengthChange': false, 'bFilter': false,
            'iDisplayLength': 10,
            'aoColumnDefs':[{
                aTargets: [3], // distance
                mRender: function(data) { return data + ' km'; },
                sType: 'unitnumber'
            }, {
                aTargets: [1],
                sType: 'lastname-sort'
            }]
        });
        var setData = window.myTable.setData = function(data) {
            table.fnClearTable();
            table.fnAddData(data);
            table.fnDraw();
        };
    
        fetchData(function(result) {
            window.myTable.data = result.data;
            setData(result.data);
        });
    
    }());

    The implementation of fetchData in the example provides hardcoded example data. You can easily replace it with a request to your service. The setData function is a convenient function to change the table data—we're going to use the same script, which will call this function to set its own data, for multiple recipes. Finally, the rest of the code is specific to DataTables and will be explained in the next section.

How it works...

The following image shows the resulting table:

To initialize the table we use the dataTable initialization function. We can pass multiple options to the function. For example, we can specify that we want 10 items per page by setting the value of the iDisplayLength property to 10.

Because we're going to render the Distance column (column 3) slightly differently than just displaying it, we add an item to the aoColumnDefs option for target column 3 that sets a custom rendering function for that column. This is a function that simply appends the km string to our number; but we could also use a more elaborate function (involving custom date formatting, unit conversions, and so on).

Paging works automatically with DataTables—the plugin appends a pager control that provides access to the previous/next page. Sorting also mostly works automatically. However, in our particular example, we need special sorting for the Name column (by last name) even though it's displayed in the format "firstname lastname". To do this, we specify a custom sort type for that column called lastname-sort. We also specify a special sort type for the Distance column called unitnumber.

DataTables allows us to define custom sort types as plugins. Custom sorters have the following properties:

  • A preprocessing function that pre-processes the column value before passing it to the sorter
  • An ascending sorting function that returns a value depending on the value of the two arguments that are passed: -1 if the first value is smaller, 0 if they are equal, or 1 if the first value is larger
  • A descending order sorting function that works similarly to the ascending sorting function

These properties allow us to implement sorting by last name for the Name column, as well as by number for the Distance column.

There's more...

Here is a simple Ajax replacement of the fetchData function, sending an Ajax request to a request handler hosted on the same domain at the path /people to retrieve the array data:

function fetchData(cb) {
    $.get('/people/').success(cb);
}

Note that this solution doesn't work very well for large datasets. While modern clients have the performance to manipulate a lot of data, bandwidth is also a consideration. A careful consideration of bandwidth requirements and the target clients (desktop or mobile) should be exercised before using this solution.

主站蜘蛛池模板: 东方市| 陆良县| 阿拉尔市| 哈巴河县| 新邵县| 梨树县| 呈贡县| 阜阳市| 泽普县| 邳州市| 北流市| 体育| 樟树市| 开原市| 永嘉县| 麻城市| 板桥市| 桃园市| 繁峙县| 平陆县| 冀州市| 皮山县| 甘孜县| 大方县| 上林县| 合山市| 岱山县| 独山县| 南充市| 兴国县| 都兰县| 荥经县| 休宁县| 定襄县| 大新县| 舞钢市| 八宿县| 贺州市| 张北县| 牟定县| 鸡西市|