inspire-tree-dom icon indicating copy to clipboard operation
inspire-tree-dom copied to clipboard

preventTreeDefault doesn't seem to work as expected

Open jeffaotal opened this issue 6 years ago • 6 comments

I would have expected the following code to have stopped the node from actually being dropped.

		tree.on("node.dragend", function(event) {
		    
			event.preventTreeDefault();
			
			alert("hi");
			
		});

But instead after I close the alert box the node is indeed dropped onto the target node.

Is there a way to intercept the drop and stop it from happening? What I'm trying to do is show a dialog which will describe the impact of making the drop and allowing the user to accept or cancel the drop.

Thanks, Jeff

jeffaotal avatar Jun 15 '18 23:06 jeffaotal

The DOM's drag/drop events don't listen for event cancel. I can look into adding support for that but I'll need to rethink the arguments a little.

viveleroi avatar Jun 16 '18 00:06 viveleroi

Ah okay. Would you suggest I do something like:

  • Listen for drop
  • Show the Confirm / Cancel dialog
  • If the user selects Cancel then somehow return the dropped node to it's original location

If that would work would you be able to help me out with what the code would look like to return the node to it's original location?

jeffaotal avatar Jun 16 '18 00:06 jeffaotal

I can't think of any easy way to handle this as-is. The drop has already finished internally by the time you get the event. The best solution I can think of is to listen for drag start, cache the parent node and offset index of where the node is currently, and if the drop is cancelled, move it back there.

http://www.inspire-tree.com/docs/current/TreeNodes.html#move

I've already tested what adding preventTreeDefault support internally will require and while I could probably get that added/released next week, I need to decide how to handle some aspects.

viveleroi avatar Jun 16 '18 00:06 viveleroi

Okay that makes sense.

How can I get the index from a DragEvent or a TreeNode so I can use the TreeNode.move function?

I'm using the following code to cache the parent node. Does this look correct?

		var parentNodeOnDragStart = null;
		
		tree.on("node.dragstart", function(event) {
		    
		    event.preventTreeDefault();
			
		    var nodeId = event.dataTransfer.getData('nodeId');

		    var nodeMoving = tree.node(nodeId);
		    
		    parentNodeOnDragStart = nodeMoving.itree.parent;
			
		});

jeffaotal avatar Jun 16 '18 01:06 jeffaotal

I think I'm not entirely sure how to get a handle on a TreeNodes object. From what I can tell a node (passed into a method like the node.dragstart handler) has an itree and a _tree. How can I get a handle on the TreeNodes object? Basically so I can then call move() on it?

My current code is below. But what's happening is that the original parent tree of the node I'm moving always ends up getting moved to the bottom of the root node.

		var parentNodeOnDragStart = null;
		
		var movingNodeOffsetIndex = null;
		
		tree.on("node.dragstart", function(event) {
		    
			event.preventTreeDefault();
			
		    var nodeId = event.dataTransfer.getData('nodeId');

		    var nodeMoving = tree.node(nodeId);
		    
		    parentNodeOnDragStart = nodeMoving.itree.parent;
		    
		    for (let i = 0; i < parentNodeOnDragStart.children.length; i++) {
		    	
		    	var maybeNodeMoving = parentNodeOnDragStart.children[i];
		    	
		    	if(maybeNodeMoving.id == nodeMoving.id) {
		    		
		    		movingNodeOffsetIndex = i;
		    		
		    		break;
		    	}
		    	
		    }
		    
		});
		
		tree.on("node.drop", function(event, source, target, index) {
			
			event.preventTreeDefault();
			
		    var confirmDrop = confirm("Are you sure you want to move this node?");
		    
		    if(!confirmDrop) {
		    	
		    	var currentIndexOfMovedNode = null;
		    	
		    	for (let i = 0; i < target.children.length; i++) {
			    	
			    	var maybeNodeMoving = target.children[i];
			    	
			    	if(maybeNodeMoving.id == source.id) {
			    		
			    		currentIndexOfMovedNode = i;
			    		
			    		break;
			    	}
			    	
			    }
		    	
		    	target._tree.move(currentIndexOfMovedNode, movingNodeOffsetIndex, parentNodeOnDragStart._tree);
		    }
		    
		});

jeffaotal avatar Jun 16 '18 03:06 jeffaotal

In case anyone else wants to do the same thing here's the code that is working.

		var nodeMovingOriginalIndex = null;
		
		var nodeMovingOriginalContext = null;
		
		tree.on("node.dragstart", function(event) {
		    
			event.preventTreeDefault();
			
		    var nodeId = event.dataTransfer.getData('nodeId');

		    var nodeMoving = tree.node(nodeId);
		    
		    nodeMovingOriginalContext = nodeMoving.context();
		    
		    nodeMovingOriginalIndex = nodeMovingOriginalContext.indexOf(nodeMoving);
		});
		
		tree.on("node.drop", function(event, source, target, index) {
			
			event.preventTreeDefault();
			
		    var confirmDrop = confirm("Are you sure you want to move this node?");
		    
		    if(!confirmDrop) {
		    	
		    	source.remove();
		    	
		    	nodeMovingOriginalContext.insertAt(nodeMovingOriginalIndex, source);
		    }
		});

jeffaotal avatar Jun 16 '18 20:06 jeffaotal