Multi select with Ctrl+Click and Shift+Click

Multi select with Ctrl+Click and Shift+Click

stwistwi Posts: 10Questions: 0Answers: 0
edited February 2013 in TableTools
Hi,

For my app I need a DataTable where multiple line selection is done via Ctrl+Click instead of the standard way implemented currently by TableTools.

With some fiddling around I came up with the following code, where you must Ctrl-Click to add a line to the multiple selection. Normal single click will select only the one line that you clicked on (like eg. Windows explorer does it).

[code]oTableTools: {
"sRowSelect": "multi",
"fnPreRowSelect": function(e, nodes) {
if (e) {
mySelectList = myDeselectList = null;
if (!e.ctrlKey) {
myDeselectList = this.fnGetSelected();
mySelectList = nodes;
}
}
return true;
},
"fnRowSelected": function(nodes) {
if (myDeselectList) {
var nodeList = myDeselectList;
myDeselectList = null;
this.fnDeselect(nodeList);
}
},
"fnRowDeselected": function(nodes) {
if (myDeselectList) {
var nodeList = myDeselectList;
myDeselectList = null;
this.fnDeselect(nodeList);
}
if (mySelectList) {
var nodeList = mySelectList;
mySelectList = null;
this.fnSelect (nodeList);
}
},
},[/code]

I hope its a good solution and helps someone.

I still need a solution for proper "Shift-Click" behaviour, but I expect this to be considerable more complex, as it involves determining the table lines in between the last clicked position and the current clicked position. My table uses "bDeferRender: true" so I can not perform DOM based searches for 'tr' elements. If anyone knows a good solution then by all means post it here.

Regards,
Stephan

Replies

  • allanallan Posts: 63,680Questions: 1Answers: 10,498 Site admin
    Very cool. Thanks for sharing that with us.

    Shift click select is something I want to add in TableTools v3 (which in fairness is a good way out with the number of things to do on DataTables first growing :-) ).

    Allan
  • stwistwi Posts: 10Questions: 0Answers: 0
    edited February 2013
    Hi again,

    Well, here it is: a working implementation of Shift+Click (and also Ctrl+Click) select using only the DataTables API :-)

    It might not (yet) be perfect, but I've done several test and it looks quite good and stable. My code mimics the Shift+Click and Ctrl+Click behaviour of Windows file explorer ... as closely as possible.

    Within your table initialisation options place this block for "TableTools" initialisation:
    [code]oTableTools: {
    "sRowSelect": "multi",
    "fnPreRowSelect": function(e, nodes, isSelect) {
    if (e) {
    mySelectList = myDeselectList = null;
    if (e.shiftKey && nodes.length == 1) {
    myDeselectList = this.fnGetSelected();
    mySelectList = myGetRangeOfRows(cgTableObject, myLastSelection, nodes[0]);
    } else {
    myLastSelection = nodes[0];
    if (!e.ctrlKey) {
    myDeselectList = this.fnGetSelected();
    if (!isSelect) {
    mySelectList = nodes;
    }
    }
    }
    }
    return true;
    },
    "fnRowSelected": mySelectEventHandler,
    "fnRowDeselected": mySelectEventHandler,
    },
    [/code]

    Within your JAVASCRIPT code place these two functions:
    [code]function mySelectEventHandler(nodes) {
    if (myDeselectList) {
    var nodeList = myDeselectList;
    myDeselectList = null;
    this.fnDeselect(nodeList);
    }
    if (mySelectList) {
    var nodeList = mySelectList;
    mySelectList = null;
    this.fnSelect (nodeList);
    }
    }

    function myGetRangeOfRows(oDataTable, fromNode, toNode) {
    var
    fromPos = oDataTable.fnGetPosition(fromNode),
    toPos = oDataTable.fnGetPosition(toNode);
    oSettings = oDataTable.fnSettings(),
    fromIndex = $.inArray(fromPos, oSettings.aiDisplay),
    toIndex = $.inArray(toPos, oSettings.aiDisplay),
    result = [];

    if (fromIndex >= 0 && toIndex >= 0 && toIndex != fromIndex) {
    for (var i=Math.min(fromIndex,toIndex); i < Math.max(fromIndex,toIndex); i++) {
    var dataIndex = oSettings.aiDisplay[i];
    result.push(oSettings.aoData[dataIndex].nTr);
    }
    }
    return result.length>0?result:null;
    }
    [/code]

    The code works independant of sorting and filtering and is independant of whether the data comes from a converted HTML table or from JSON data array. My application uses JSON data array, so thats what I tested it with. I do not have the possibility to test against an AJAX data source, so I can not make any guaranties for that. It might be nice if someone else could test this.

    Some notes on the code:
    * sadly at this point I do not have a full standalone piece of sample code for you, so you'll have to do some (minor) copy/pasting and renaming yourself
    * at one point you will see "cgTableObject". This is the object where I store the reference to my actual DataTable => rename it to your table object (or use jQuery),
    * dont forget to declare the "mySelectList" etc. variables somewhere, maybe even rename them to something nicer,
    * "mySelectEventHandler" has become a separate function because I use it twice in absolutely identical form
    * "myGetRangeOfRows" can be condensed down to a smaller form, but thats code cleanup for later, the present form isgeared towards being debug friendly

    Regards,
    Stephan
This discussion has been closed.