This is a migrated thread and some comments may be shown as answers.

Add custom drop event to TreeView node to handle drops from File Explorer

3 Answers 335 Views
TreeView
This is a migrated thread and some comments may be shown as answers.
Scott
Top achievements
Rank 1
Scott asked on 16 Jun 2015, 06:00 PM

I'm trying to add a custom drop event to each tree view node so that I can handle the 'drop' event when a file is dropped onto the node element from Windows File Explorer.  My html code (with the style section removed) looks like this:

 

<div id="example">
        <div class="demo-section k-header">
            <div class="box-col" style="width: 300px">
                <h4>Select a node</h4>
                <div class="files"
                     data-role="treeview"
                     data-drag-and-drop="false"
                     data-text-field="name"
                     data-spritecssclass-field="type"
                     data-bind="visible: isVisible,
                            source: files,
                            events: { dataBound: onDataBound }"></div>
            </div>
        </div>
        
        <script>
            $(document).ready(function ()
            {
                $("#treeview").kendoTreeView();
            });
        </script>
    </div>

 

I'm binding the view model like this:

<script>
    var viewModel = kendo.observable({
        isVisible: true,
        onDataBound: function (e)
        {
            if (e.node)
            {
                var dataItem = e.sender.dataItem(e.node);
 
                dataItem.bind('drop', function (e1)
                {
                    alert('dropped on item');
                });
            }
        },
        files: kendo.observableHierarchy(jobBookAPI.directoryContents)
    });
    kendo.bind($("#example"), viewModel);
 
</script>

My data looks like this:

var jobBookAPI = new function ()
{
    // Public data
 
    this.directoryContents =
        [
            {
                name: "My Web Site", type: "folder", expanded: true, items:
                [
                    {
                        name: "images", type: "folder", expanded: true, items:
                        [
                            { name: "logo.png", type: "image" },
                            { name: "my-photo.jpg", type: "image", id: 12345 }
                        ]
                    },
                    {
                        name: "resources", type: "folder", expanded: true, items:
                        [
                            { name: "resources", type: "folder" },
                            { name: "zip", type: "folder" }
                        ]
                    },
                    { name: "about.html", type: "html" },
                    { name: "index.html", type: "html" }
                ]
            }
        ];
 
};
 

 

The drop event does not fire when I drag a file onto a node.  I've tried replacing 'drop' with 'click' just to see if I can fire a click event, but that event doesn't fire when a node is clicked.  I think that what I'm trying to do should be possible because I've use this same method with simple DIV elements and files dropped on them from File Explorer cause the drop event to fire perfectly.

Any ideas what I'm doing wrong?

Thanks. 

 

 

3 Answers, 1 is accepted

Sort by
0
Scott
Top achievements
Rank 1
answered on 16 Jun 2015, 08:55 PM

I wasn't able to come up with a solution within the onDataBound event, but I was able to make it work by enumerating each node and adding the drop event to it after binding the data.  Like this:

 

var viewModel = kendo.observable({
    isVisible: true,
    files: kendo.observableHierarchy(jobBookAPI.directoryContents)
});
kendo.bind($("#example"), viewModel);
 
// Makes sure the dataTransfer information is sent when we handle file drops
jQuery.event.props.push('dataTransfer');
 
var allNodes = $('#example').find(".k-top,.k-mid,.k-bot");
for (var i = 0; i < allNodes.length; i++)
{
    $(allNodes[i]).bind('dragenter', function ()
    {
        $(this).css({ 'box-shadow': 'inset 0px 0px 20px rgba(0, 0, 0, 0.1)', 'border': '4px dashed #bb2b2b' });
        return false;
    });
 
    // Must handle dragover or drop won't fire.
    $(allNodes[i]).bind('dragover', function ()
    {
        return false;
    });
 
    $(allNodes[i]).bind('dragleave', function (e)
    {
        $(this).css({ 'box-shadow': 'none', 'border': 'none' });
        return false;
    });
 
    $(allNodes[i]).bind('drop', function (e)
    {
        $(this).css({ 'box-shadow': 'none', 'border': 'none' });
        if (e.dataTransfer)
        {
            var files = e.dataTransfer.files;
            alert('dropped on item outer');
        }
        return false;
    });
}

0
Scott
Top achievements
Rank 1
answered on 16 Jun 2015, 10:03 PM

Now the problem is that I seem to have no way to match the target node of the drop to its data source in the drop handler:

 

$(allNodes[i]).bind('drop', function (e)
    {
        $(this).css({ 'box-shadow': 'none', 'border': 'none' });
        if (e.dataTransfer)
        {
            var files = e.dataTransfer.files;
           // How do I match the e.target back to the data?
            alert('dropped on item outer');
        }
        return false;
    });

 

The div element in e.target contains no uid.  I could dig through the spans to grab the node name but that wouldn't work if there were two nodes of the same name in different branches.  I keep seeing code like this:  var treeView = $("#treeView").data("kendoTreeView"); on forum posts but that always returns null when binding to a view model.  Any way I can make this work?

 

0
Accepted
T. Tsonev
Telerik team
answered on 19 Jun 2015, 06:50 AM
Hello,

Please accept my apologies for the delayed response.

Your last snippet is pretty close to what I would recommend. The event handler should go on the "k-item" element instead as that's what holds the uid.
Also, your TreeView is missing an ID. That's why you're unable to get its instance.
<div class="files" id="treeview" ...
var treeView = $("#treeview").kendoTreeView();


$("#example .k-item")
  .bind('drop', function (e)
    {
        if (e.dataTransfer)
        {
            var files = e.dataTransfer.files;
            var dataItem = treeView.dataItem(this);
            ...
        }
    });

I hope this helps.

Regards,
T. Tsonev
Telerik
 
Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
 
Tags
TreeView
Asked by
Scott
Top achievements
Rank 1
Answers by
Scott
Top achievements
Rank 1
T. Tsonev
Telerik team
Share this question
or