Drag and Drop - source and target constraints

Hey,

Complete beginner here with Webix but really liking what they’re doing!

I’ve knocked together my first basic test app, so far so good. Now I would like to make it a little more intelligent and I’m after some help please?

I have a tree with two parent nodes, Section1 and Section2. Each parent has a couple of child nodes (options) and I’d like to be able to drag n drop Section1’s children onto Section1’s list and Sections2’s children onto Sections2’s list. What I don’t want to be able to do is drag Section1’s children into Section2’s list or vice versa, so I’d like to code some constraints to stop this from happening.

<!DOCTYPE HTML>
<html>
    <head>
	<script type="text/javascript" src="http://cdn.webix.com/edge/webix.js"></script>
	<link rel="stylesheet" href="http://cdn.webix.com/edge/webix.css">

    </head>
    <body>

        <script type="text/javascript" charset="utf-8">
		


 webix.ui({
			rows:[
					{ type:"header", template:"My App!" },
					
				{ cols:[
		    
					{ view:"tree",id: "0",drag:"source",

						data: [
								{ id:"1", open:true, value:"Section1",
									data:[
											{ id:"1.1", value:"Option1" },
											{ id:"1.2", value:"Option2" },
											{ id:"1.3", value:"Option3" }
										 ]
								},
								
								{ id:"2", open:true, value:"Section2", 
									data:[
											{ id:"2.1", value:"Option1" },
											{ id:"2.2", value:"Option2" },
											{ id:"2.3", value:"Option3" },
											{ id:"2.4", value:"Option4" }
										 ]
								},
							  ],gravity:0.325, select:true },
      {view:"resizer" },
	  
			{rows:[
					{view:"list",drag:"target",
						data: [
								{id:"3", value:"Only Section1 Options can be dropped here:"}
							  ],gravity:0.25,scroll:false
					},
							  
					{ view:"resizer" },
	  
					{view:"list",drag:"target",
						data: [
								{id:"4", value:"Only Section2 Options can be dropped here:"}
							  ],gravity:0.35
					},
							  
					{ view:"resizer" },
					
					{view:"list",
						data: [
								{id:"5", value:"This is for results - no drops here:"}
							  ]
					}
				  ]
			}
						]
				}
				]
})

			
        </script>
		
    </body>
</html>

Has anyone any ideas how to do this? Also how can I setup the tree items to copy when they’re dragged and not moved.

Many Thanks for any help,

Slash.

You can use onBeforeDragIn handler to further customize drop-allow behaviors

on:{ onBeforeDragIn:function(context){ 
    return context.from.getParentId(context.source) == 1 
}},

http://webix.com/snippet/0b836234

Thank you very much maksim!!! This is exactly what I was after.

Have a great weekend

Slash.

One more question please. How can I then capture the contents of the lists? Should I try a form or build a variable/array?

Ultimately I would like to pass the contents of the lists to php to execute a stored procedure but for now I would like to start simple and just capture the lists contents?

Thanks again!

If you need all the data from the list

var text = JSON.stringify( list.serialize() );

You can link to some REST url, so list component will send all updates to server side after each insert/update/delete

http://docs.webix.com/desktop__server_rest.html

Excellent thanks maksim, do you need to declare the list in a var first?

You can access it by ID

{view:"list", id:"list1", drag:"target",
....
$$("list1").serialize();

Thanks again maksim, it’s taken me a couple of attempts but I’ve got the basics working now. Appreciate all your help!

Sorry, more help needed please. I’ve added a simple button that on click posts the list data to a simple php page. This is all working fine for one list but I have two and would like to post the contents of both.

click:“webix.ajax().post(‘search.php’, JSON.stringify($$(‘types’).serialize()), ‘callback’);”

I’m not sure how to combine the contents of both lists, I’ve tried:

click:“webix.ajax().post(‘search.php’, JSON.stringify($$(‘types’).serialize+$$(‘filters’).serialize()), ‘callback’);”

But can’t get it to work.

Many Thanks for the help once again.

click:function(){
  webix.ajax().post('search.php',{
     list1: JSON.stringify($$('types').serialize()),
     list2: JSON.stringify($$('filters').serialize())
  }), 'callback');"

As result you will have $_POST[“list1”] and $_POST[“list2”] on a server side.

Legend, I’ll will try this tonight. Thanks again!

Worked a treat, thanks again maksim!

Hi maksim,

Sorry to bother you again, I had been getting on really well but I’m afraid I’m stuck again. Any ideas on why my active list buttons don’t register correctly? I haven’t given them any particular actions as of yet but I can see from the debug console (core@undefined) they’re not working correctly eg can’t be clicked?

Here’s my code:

            {view:"activeList",id:"filters",drag:"target",
			height:100,

			on:{	
			
			onBeforeDragIn:	
			function(context){ 
						
                		return context.from.getParentId(context.source) == 2 ;
						
                },
			onAfterDrop:
			function(){ 
						webix.extend(this, webix.OverlayBox);
						this.showOverlay("<div style='margin:15px; font-size:20px;'></div>");
					},
										
			onAfterLoad:
			function(){
						if (!this.count()){ //if there are no data items
						webix.extend(this, webix.OverlayBox);
						this.showOverlay("<div style='margin:15px; font-size:20px;'>&nbsp;&nbsp;&nbsp; Drag Section 2 Here:</div>");
										  }
					}},
							

			activeContent:{
										
            numcounter:{
                view:"counter",
                width:100
				},
            deleteButton:{
				id:"deleteButtonId",
				view:"button",
				value:"Remove",
				width:100
				
				
				}
			
			},

			data:[],
			type: {
				height:70
					},				

		template: "<div class='title'>#value#</div><div class='counters'>{common.numcounter()}</div><div class='buttons'>{common.deleteButton()}</div><div class='buttons'>{common.editButton()}</div>",		
             
            }

Any help would be greatly appreciated.

Thanks again,
Slash.

As far as I can see, buttons works correctly

http://webix.com/snippet/443057bb

The (core@undefined) in the console, is a global webix.onClick event, which fire each time when click occurs anywhere on the page

Ah sorry, I think I over simplified my example. Try this one, drag an option from section 2 of the tree into section 2 list on the right. The buttons don’t seem to work:
http://webix.com/snippet/3dcda2fb

Thanks very much for taking the time to look into this.
Slash.

In onDrop handler, you need to call hideOverlay instead of showOverlay
http://webix.com/snippet/21f3bb20

With previous version of a code you have a transparent overlay over button, which catches mouse events and prevent normal event processing

D’oh, I should’ve been able to figure that out. Thanks so much for all your help once again.

Slash.

Hey maksim, I was wondering if I could ask you another question?

I have now successfully got my app posting parameters to php and executing a stored procedure against a MySQL db. If I do a callback function and message out the data response I can see the json formed results of the query which is great. What I need to now do is display these results in a data view and not sure how? Is there some way to tell a data view to get its data from a callback function or some other way?

Many thanks for any help once again!

Slash.

Is there some way to tell a data view to get its data from a callback function or some other way?

You can use something like

function callback(data){
   $$("dataviewid").parse(data);
}

And if you are using a webix.ajax ( or any other promise based ajax library, you can use

$$("dataviewid").parse( webix.ajax().post("data.php") );

Which will do an ajax post and will load the response into the target component.

Thanks once again maksim - really appreciate it. Easy when you know how.

Slash.