Thursday, February 27, 2014

JQuery Dynatree - Limit number of multiple selections

JQuery Dynatree is another simple and useful plugin for display tree structures. Additionally it allows selection of nodes, single selection (radio-button) or multiple selections (Check-box). A simple multiple choice dynatree can be loaded with a script similar to this:
$("#dynaTree").dynatree({
        checkbox: true,
        classNames: { checkbox: "dynatree-checkbox " },
        selectMode: 2,
        children: TreeData,
        onSelect: function (select, node) {
            var selNodes = node.tree.getSelectedNodes();           
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });
            var selKeys = $.map(selNodes, function (node) {
                return node.data.key;
            });           
        },
        onClick: function (node, event) {
            if (node.getEventTargetType(event) == "title") {
                    node.toggleSelect();
                }
        },
        onKeydown: function (node, event) {
            if (event.which == 32) {
                node.toggleSelect();
                return false;
            }
        }
    });
 This tree has selecteMode set to 2 which enables multiple selections. There is no limit to the number of selections. So what if we want to limit the number of selections to say, 5? Here’s how to do it. Every time an click event occurs on the tree onClick function is called first. Right now it only toggles selection if a title is clicked (we don’t need to toggle if click event is “checkbox” because it will result a double toggle). In order to limit selections, what we have to do is get the number of already selected nodes and if it is greater than or equals to 5 simply return false. Then it will not call onSelect function which add node to selected nodes. Here is the code:
$("#dynaTree").dynatree({
        checkbox: true,
        classNames: { checkbox: "dynatree-checkbox " },
        selectMode: 2,
        children: TreeData,
        onSelect: function (select, node) {
            var selNodes = node.tree.getSelectedNodes();
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });
            var selKeys = $.map(selNodes, function (node) {
                return node.data.key;
            });           
        },
        onClick: function (node, event) {
            var selNodes = node.tree.getSelectedNodes();
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });           
            if (node.getEventTargetType(event) == "title") {
                    if (selTitles.length >= 5 ) {
                        //disable toggle if selection limit is exceeded
                        return false;
                    }                  
            }               
             else if (node.getEventTargetType(event) == "checkbox") {
// disable selection if hospital limit is exceeded
                    if (selTitles.length >= 5 ) {
                        return false;
                    }                   
               }
        },
        onKeydown: function (node, event) {
            if (event.which == 32) {
              var selNodes = node.tree.getSelectedNodes();
              var selTitles = $.map(selNodes, function (node) {
                                  return node.data.title;
                            });           
              if (selTitles.length >= 5 ) {
                 return false;
              }                   
              else{
                node.toggleSelect();
                return false;
              }
            }
        }
    });

Apart from just disabling the selections when limit exceed, we might want to toggle selection if an already selected node is clicked again so that we can uncheck one node and select another node in its place. For that, we need to check whether the clicked node is selected or not. If selected we can toggle the selection. I modified the code to enable it:
$("#dynaTree").dynatree({
        checkbox: true,
        classNames: { checkbox: "dynatree-checkbox " },
        selectMode: 2,
        children: TreeData,
        onSelect: function (select, node) {
            var selNodes = node.tree.getSelectedNodes();
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });
            var selKeys = $.map(selNodes, function (node) {
                return node.data.key;
            });           
        },
        onClick: function (node, event) {
            var selNodes = node.tree.getSelectedNodes();
            var selTitles = $.map(selNodes, function (node) {
                return node.data.title;
            });           
            if (node.getEventTargetType(event) == "title") {
              // click on a title
                    if (selTitles.length >= 5 && !node.isSelected()) {
              //disable toggle if limit is exceeded and node is not a selected one
                        return false;
                    }                  
                     else {
                           node.toggleSelect();
                     }
            }               
             else if (node.getEventTargetType(event) == "checkbox") {
              // click on a checkbox
                    if (selTitles.length >= 5 && !node.isSelected()) {
            //disable selection if hospital limit is exceeded and node is not a selected one
                        return false;
                    }                   
               }
        },
        onKeydown: function (node, event) {
            if (event.which == 32) {
var selNodes = node.tree.getSelectedNodes();
              var selTitles = $.map(selNodes, function (node) {
                                  return node.data.title;
                            });           
              if (selTitles.length >= 5 && !node.isSelected()) {
                 return false;
              }                   
              else{
                node.toggleSelect();
                return false;
              }
            }
        }
    });



1 comment:

  1. Hello, Can you let me know if I have to select multiple nodes in dynatree how I can do it? For example I have an arraylist of id's(nodes) which I need to use to select each node. I used $('#tree').dynatree("gettree").selectkey(arraylist[0]);. THis only selects the first node present in the arraylist , but when I put this code in a for loop like - for(int i=0;i<arraylist.length;i++){ var exp =$('#tree').dynatree("gettree").selectkey(arraylist[i]); exp.focus(); exp.makeVisible();} , it does not select all the keys , only first key is selected.

    ReplyDelete