Disable sorting for specific rows.

Disable sorting for specific rows.

Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
edited August 2011 in General
How can I disable sorting for specific rows?

It is necessary for me, that these lines were always shown in the table beginning, and sorting would occur already after them.

Is that possible?

Replies

  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    It's possible. But you'll need to write a (simple) sorting plugin.

    What is the criteria that identifies those rows?
  • Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
    Each cell in this row is a description of the cell in the header.
  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    If you can be more specific, I can help you write the sorting plugin functions.
  • Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
    edited August 2011
    Sorry table not in english, but I think you could understand what I am talking about.
    The first two rows (marked red) must be disabled from sorting.
    In this rows is a description of the header.
    http://savepic.net/1817279.jpg
  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    edited August 2011
    Will they always have the same value in the first column? You could have the sort function ignore those rows with those values.
    [code]
    jQuery.fn.dataTableExt.afnSortData['custom'] = function ( oSettings, iColumn )
    {
    var aIndexData = [], aColData = [];

    $( 'td:eq(0) input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
    aIndexData .push( this.value );
    } );

    $( 'td:eq('+iColumn+') input', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
    aColData .push( this.value );
    } );

    for (i in aIndexData) {
    // replace between { and } with the real value of your rows at first column
    if (aIndexData[i] == "{put row 1 col 1 here}" || aIndexData[i] == "{put row 2 col 1 here}" )
    aColData[i] = aIndexData[i];
    }
    return aColData;
    }

    jQuery.fn.dataTableExt.oSort['custom-asc'] = function(x,y) {
    if (x == "{put row 1 col 1 here}") return -1; // keep this row at top
    if (y == "{put row 1 col 1 here}") return 1; // keep this row at top

    if (x == "{put row 2 col 1 here}") return -1; // keep this row next to top
    if (y == "{put row 2 col 1 here}") return 1; // keep this row next to top

    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    };

    jQuery.fn.dataTableExt.oSort['custom-desc'] = function(x,y) {
    if (x == "{put row 1 col 1 here}") return 1; // keep this row at top
    if (y == "{put row 1 col 1 here}") return -1; // keep this row at top

    if (x == "{put row 2 col 1 here}") return 1; // keep this row next to top
    if (y == "{put row 2 col 1 here}") return -1; // keep this row next to top

    return ((x < y) ? 1 : ((x > y) ? -1 : 0));
    };

    // then use "sType": "custom" for all columns except first column
    [/code]

    OR are they the only rows that dont have nyet/da as all the values? You could have the sort function ignore values that are not nyet/da. It looks like row 2 is a date and row 1 is text.
    [code]
    jQuery.fn.dataTableExt.oSort['nyetda-asc'] = function(x,y) {
    if (isNotDateNotNyetDa(x)) return -1; // keep this row at top
    if (isNotDateNotNyetDa(y)) return 1; // keep this row at top

    if (isDate(x)) return -1; // keep this row next to top
    if (isDate(y)) return 1; // keep this row next to top

    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    };

    jQuery.fn.dataTableExt.oSort['nyetda-desc'] = function(x,y) {
    if (isNotDateNotNyetDa(x)) return 1; // keep this row at top
    if (isNotDateNotNyetDa(y)) return -1; // keep this row at top

    if (isDate(x)) return 1; // keep this row next to top
    if (isDate(y)) return -1; // keep this row next to top

    return ((x < y) ? 1 : ((x > y) ? -1 : 0));
    };

    function isNotDateNotNyetDa(s) {
    if (s == "Da") return false; // but translate this to unicode instead of "Da"
    if (s == "Nyet") return false; // but translate this to unicode instead of "Nyet"
    if (isDate(s)) return false;

    return true;
    }

    function isDate(s) {
    aDate = s.split('.');
    // continue date validation here.. return true or false
    }

    // then use "sType": "nyetda" for all columns except first column
    [/code]

    OR a third (easy) option would be to put those rows into the THEAD
  • Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
    Ok I tried your solutions. The first is half useful for me, second is better for me, third - not an option.
    May be you can tell me how to disable from sorting rows without using the classes, only those which are written in script. Because every cell of my table already have a classes.
  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    edited August 2011
    [quote]Walter_Stolz said: disable from sorting rows without using the classes,[/quote]

    not sure what you mean by "the classes". the sort functions don't rely on css classes, they rely on setting sType for the column, which tells DataTables which sorting functions to use. they won't interfere with any CSS classes you use to color the cells.

    specify using aoColumnDefs OR aoColumns.
    [code]
    aoColumnDefs: [ { aTargets: [1,2,3,4,5,6], sType: "custom"}] ,
    [/code]
  • Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
    Sorry my mistake. I thought, that you mean set class="sType" for the first column and for other class="custom".
    After your last post all is clear.
  • Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
    Ok I'll tested your scripts.
    First script ("sType": "custom") with my inserted data didn't do nothing.
    Second script ("sType": "nyetda") disable sorting on all first column and fixing first two rows at top, but I need only that first two lines have been fixed, and others would continue sorting.
  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    because I don't know how to enter cyrillic characters, you can't use the above code literally. you will have to change values

    [code]
    if (s == "Da") // change "Da" to cyrillic string
    [/code]

    [code]
    if (x == "{put row 1 col 1 here}") return -1; // replace value in string with Cyrillic string. don't keep the { and } characters
    [/code]
  • Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
    [quote]fbas said: if (x == "{put row 1 col 1 here}") return -1;  // replace value in string with Cyrillic string. don't keep the { and } characters[/quote]

    First script: I replaced the text between the brackets {put row 1 col 1 here} with the my own Cyrillic text from the first cell in the first column - no effect.
    Second script: I replaced "Da" with with the my own Cyrillic text from the first cell in the first column - columns were fixed, sorting disabled in all column.
  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    edited August 2011
    version 2 works, just have to reverse the values in the descend.. should look like ascend. version 1 is probably also an easy fix.

    also, you need to define function isDate(s). I didn't write the function here.

    http://www.beg.utexas.edu/_work/dt/nyetda.htm

    revision:
    [code]
    var oTable;
    jQuery.fn.dataTableExt.oSort['nyetda-asc'] = function(x,y) {
    if (isNotDateNotNyetDa(x)) return -1; // keep this row at top
    if (isNotDateNotNyetDa(y)) return 1; // keep this row at top

    if (isDate(x)) return -1; // keep this row next to top
    if (isDate(y)) return 1; // keep this row next to top

    return ((x < y) ? -1 : ((x > y) ? 1 : 0));
    };

    jQuery.fn.dataTableExt.oSort['nyetda-desc'] = function(x,y) {
    if (isNotDateNotNyetDa(x)) return -1; // keep this row at top
    if (isNotDateNotNyetDa(y)) return 1; // keep this row at top

    if (isDate(x)) return -1; // keep this row next to top
    if (isDate(y)) return 1; // keep this row next to top

    return ((x < y) ? 1 : ((x > y) ? -1 : 0));
    };

    function isNotDateNotNyetDa(s) {
    if (s == "da") return false; // but translate this to unicode instead of "Da"
    if (s == "nyet") return false; // but translate this to unicode instead of "Nyet"
    if (isDate(s)) return false;

    return true;
    }

    function isDate(s) {
    aDate = s.split('.');
    if (aDate.length == 3) return true;
    // continue date validation here.. return true or false

    return false;
    }

    // then use "sType": "nyetda" for all columns except first column

    $(document).ready(function() {

    oTable = $('#nyetda').dataTable({
    aoColumnDefs: [
    { aTargets: [1,2,3], sType: "nyetda" }
    ],
    aaSorting: [ [1, 'desc'] ]
    });
    });
    [/code]
  • Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
    Thank you for Your example, this script works perfectly for my table, I just replace English "da" with russian "Да" and it works, but there is a little bit problems.

    1) Cells in the first column also must be fixed.
    2) The data in columns is not only Yes("Da") or No("Nyet"), there are more than 10 different values in table and write in script [code]if (s == "text_availible_for sorting") return false;[/code] for every sortable cell it to much of code.

    May be the easiest way create the script with function, witch keeps at top and disable from sorting the data between selected ?

    [code]

    Text_row1_col1
    Text_row1_col2
    Text_row1_col3
    Text_row1_col4

    [/code]
    or
    [code]

    Text_row1_col1
    Text_row1_col2
    Text_row1_col3
    Text_row1_col4


    Text_row2_col1
    Text_row2_col2
    Text_row2_col3
    Text_row2_col4

    [/code]
  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    1) if you don't want column 1 sortable, disable sorting on that column
    [code]
    $(document).ready(function() {

    oTable = $('#nyetda').dataTable({
    aoColumnDefs: [
    { aTargets: [0], bSortable: false }
    { aTargets: [1,2,3], sType: "nyetda" }
    ],
    aaSorting: [ [1, 'desc'] ]
    });
    });

    [/code]


    2) you can rewrite this in many ways that don't require much coding, i.e. using an array of values or using switch statement.
    [code]
    function isNotDateNotNyetDa(s) {
    switch(s) { // note: switch statements allow fall through, unless you use "break"
    case "da":
    case "nyet":
    case "...": return false;

    }

    if (isDate(s)) return false;

    return true;
    }
    [/code]

    but if it's easier to test for positive rather than negative, change the code how you see fit

    ----


    for the other approach you mention, using an ID or CSS class the TR element , you need something more than the osort API functions we are using. the osort functions only have access to the values in that column, for text compare. but you can do what you are asking if you use the afnSortData interface, which gives you the oSettings object and the target column number. http://www.datatables.net/development/sorting

    from the oSettings object you can get all row nodes, and that way get all data elements in each row, or the css values for the row. afnSortData functions need to return an array that represents values to sort on for the column. you can combine the use of the osort functions and sType with the afnSortData function.
  • Walter_StolzWalter_Stolz Posts: 46Questions: 6Answers: 0
    Thank you for your replies.
    I'll make my own conclusions.
  • RaaghuRaaghu Posts: 1Questions: 0Answers: 0
    Hi can i do the same thing for not sorting lastrow, I mean i want to keep the last row as is , it should nt be part of sorting, please let me know
  • fbasfbas Posts: 1,094Questions: 4Answers: 0
    yes
  • burntsausageburntsausage Posts: 9Questions: 0Answers: 0
    So what was the fix for version 1?
  • cheimbeckercheimbecker Posts: 1Questions: 0Answers: 0
    edited May 2012
    Need existed to address original poster request for sort locking (preventing sort) of specific rows in DataTables using combination of afnSortData and oSort with sType declarations. This proposal consolidates a few related discussions which all hint at the same end (see references below). Being that I could not find example code that finished the suggested implementation, here is a possible solution with examples.

    The solution proposed below addresses need for a table that has a total row (as the last row) which must not be included in the column sorting method.

    Using the id tag of the TD, assign a custom sort function 'dom-text' which sets the data array value for a given column to "sortfalse" id TD id="sortfalse". This override value is then used in the assigned sType based sort plug-ins to skip rows marked as "sortfalse.

    Author note: If there is a more efficient looping technique than what I am using in afnSortData['dom-text'] to obtain the column values & TD id - I would certainly accept any suggested improvements. Performance over very large data sets is not validated.


    //EXAMPLE HTML:
    [code]



    ABC
    123






    A1


    1





    B1


    2





    C1


    3





    TOTALS:


    6





    [/code]

    //DATATABLE INITIALIZATION CODE:
    [code]
    jQuery.fn.dataTableExt.afnSortData['dom-text'] = function ( oSettings, iColumn )
    {
    var aData = [];
    $( 'td ', oSettings.oApi._fnGetTrNodes(oSettings) ).each( function () {
    var col = $(this).parent().children().index($(this));
    if (col == iColumn){
    var cid = $(this).attr('id');
    var val = $(this).html();
    if (cid == "sortfalse"){
    aData.push( "sortfalse" );
    }else{
    aData.push( val );
    }
    }
    } );
    return aData;
    }
    [/code]

    //MODIFIED SORTING PLUGIN,
    //EXAMPLE USING THE ONE PROVIDED VIA http://www.datatables.net/plug-ins/sorting
    // See > "Formatted Numbers"
    [code]
    jQuery.fn.dataTableExt.oSort['formatted-num-asc'] = function(a,b) {
    /* Remove any formatting */
    if (a != null && b != null && a != "sortfalse" && b != "sortfalse"){
    //CH: DO NOT SORT IF ROW IS ASSIGNED id="sortfalse"
    var x = a.match(/\d/) ? a.replace( /[^\d\-\.]/g, "" ) : 0;
    var y = b.match(/\d/) ? b.replace( /[^\d\-\.]/g, "" ) : 0;
    /* Parse and return */
    return parseFloat(x) - parseFloat(y);
    }
    return 0;
    };

    jQuery.fn.dataTableExt.oSort['formatted-num-desc'] = function(a,b) {
    if (a != null && b != null && a != "sortfalse" && b != "sortfalse"){
    //CH: DO NOT SORT IF ROW IS ASSIGNED id="sortfalse"
    var x = a.match(/\d/) ? a.replace( /[^\d\-\.]/g, "" ) : 0;
    var y = b.match(/\d/) ? b.replace( /[^\d\-\.]/g, "" ) : 0;
    return parseFloat(y) - parseFloat(x);
    }
    return 0;
    };
    [/code]

    //EXAMPLE CREATE DATATABLES
    [code]
    jQuery('#example').dataTable( {
    "sScrollY": 600,
    "bPaginate": false,
    "bInfo": false,
    "bAutoWidth": false,
    "bSortClasses": false,
    "sScrollX": "100%",
    "aaSorting": [],
    "bFilter": false,
    "bDestroy": true,
    "aoColumns": [ { "sSortDataType": "dom-text", "sType": "formatted-num"},
    { "sSortDataType": "dom-text", "sType": "formatted-num" } ]
    } );
    [/code]


    REFERENCES:
    http://www.datatables.net/forums/discussion/1493/live-dom-sorting/p1
    http://datatables.net/forums/discussion/6089/disable-sorting-for-specific-rows./p1
    http://www.datatables.net/examples/plug-ins/dom_sort.html
    http://datatables.net/forums/discussion/5331/datatables-warning-...-requested-unknown-parameter/p1
    http://datatables.net/usage/columns
This discussion has been closed.