Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

dnd, how to restrict dropping to certain node types?

Tags:

jstree

I have 37 different node types. I am trying to implement drag and drop. This works but I need to restrict exactly which types can be dragged and where they can be dropped. I can't find any useful information in the docs unfortunately (http://www.jstree.com/documentation).

So far I have tried three methods:

first: defining return values of true or false in the drag_check callback depending on the node type:

$("#demo1").jstree({
    "dnd" : {
        "drag_check" : function () {

second: binding to the prepare_move.jstree event and returning true or false values depending on the node type:

.bind("prepare_move.jstree", function (e, data) {
   if (data.rslt.o.attr("typ") === "tpop") {

third: using the types plugin and defining valid children there:

$("#tree").jstree( {
    "types": {
        "type_attr": "typ",
        "valid_children": ["ap_ordner_pop", "ap_ordner_apziel", "ap_ordner_erfkrit", "ap_ordner_apber", "ap_ordner_ber", "ap_ordner_beob", "iballg", "ap_ordner_ibb", "ap_ordner_ibartenassoz"],
        "types": {
        "ap_ordner_pop": {
            "valid_children": "pop"
        },
        "pop": {
            "valid_children": ["pop_ordner_tpop", "pop_ordner_popber", "pop_ordner_massnber"],
            "new_node": "neue Population"
        },
        "pop_ordner_tpop": {
            "valid_children": "tpop"
        }

But I can still drop most nodes nearly anywhere. How must this be done? Or can you point me to a good example?

Help is much appreciated.

like image 237
Alex Avatar asked Jun 12 '12 15:06

Alex


2 Answers

For those of you looking for answers using jstree v3. The crrm plugin has been removed, and instead you will want to use 'check_callback'.

In my case all I wanted to do was stop child items from being dragged into other child items. There may be a better way to do this but after hours of little progress, this is what worked for me.

I believe you also need to set 'check_while_dragging' dnd option to true in order to trigger 'check_callback' while dragging.

Here's my jsTree initialisation:

$("#jsTree").jstree({
            'core': {
                'data': window.treeData,
                'themes': {
                    'icons': false
                },
                'check_callback': function(operation, node, node_parent, node_position, more) {
                    // operation can be 'create_node', 'rename_node', 'delete_node', 'move_node' or 'copy_node'
                    // in case of 'rename_node' node_position is filled with the new node name

                    if (operation === "move_node") {
                        return node_parent.original.type === "Parent"; //only allow dropping inside nodes of type 'Parent'
                    }
                    return true;  //allow all other operations
                }
            },
            "state": { "key": "<%=Request.QueryString["type"]%>_infotree" },
            "dnd": {
                check_while_dragging: true
            },
            "plugins": ["state", "dnd", "types"]
        })
like image 52
Tonic Avatar answered Nov 16 '22 23:11

Tonic


On the target(s) you would need to check if you are allowed to drop an object there. It seems you have some mechanism to smell the object as you indicated with:

 if (data.rslt.o.attr("typ") === "tpop")

That's good. Use that technique to discriminate one object type from another when performing a multitree operation. In the example below I use class names from source and target to do my own unique "smell test". Don't copy and paste or you'll get confused. You need to use your own type of test to accept/reject a drag and drop from one tree to another. All of my testing is done in the crrm check_move function.

.jstree({
 "crrm" : {
    input_width_limit : 200,
    move : {
        always_copy     : "multitree", // false, true or "multitree"
        open_onmove     : false,
        default_position: "last",
        check_move      : function (m) { 
                            if(!m.np.hasClass("someClassInTarget")) return false;
                            if(!m.o.hasClass("someClassInSource")) return false;
                            return true;
                          }
    }
 },
 "dnd" : {
    copy_modifier   : $.noop,
    drop_target     : ".someWrapperClassInSource",
    drop_check      : function (data) { return true; },
    drop_finish     : function (data) {
                            $.jstree._reference(this.get_container()).remove($(data.o));
                      },
    drag_target     : ".someClassInSource",
    drag_finish     : function (data) {;},
    drag_check      : function (data) { return { after : false, before : false, inside : true }; }
 },
like image 34
MMeah Avatar answered Nov 17 '22 00:11

MMeah