This project was a mere fun project that came about because of a lack of forward planning in the design process.
I had contended with the Business Analyst that this project would take a significant amount of time to finish, and that it may be more facile to have an uncomplicated control, like two list controls, or 1 list that includes the initial groups, and 1 or more with the child objects, which in my own case was substations and generating units. But, the B.A. drawn back and persisted on having two look-alike tree controls with multiple levels of Child objects, (of course displayed by a different icon for each).
I did my findings to know exactly what kind of control I could basically reuse, as I thought there should be an implementation of drag and drop between two tree controls! Not to my surprise, there wasn’t. It’s insignificant to implement drag and drop between two tree controls, but only with the exact same objects between the two.
If you desire to have more than one ‘level’, such control don’t exist anywhere, at least at that time ( few years back from now). Also, we were confined to only using free controls, like Jquery plugins, and such. some Other commercial products also didn’t carry out what I wanted, like Infragistics or teleric.
So, I reached a conclusion on jstree (www.jstree.com), which I considered great at least. But, there was no support, and not a lot of developers used it as at then. But, it did have events that descried drag and drop between disparate cases of jstree, which at least was a good inception. By the way, the counselling I got from other ‘developers’ on our team was that this little project was not feasible, and to just give up and implement it in a less significnant matter, using lists. But, I was determined so I moved ahead, and got to work with jstree.
My elucidation used recursion, which seemed like the simplest way to achieve my aim. As, if you actually think about this, before starting work on it, (unfortunately not a lot of developers actually think about logic and design before coding nowadays), you must implement logic to avoid drag and drop of nodes on a different ‘level’ of the present object that you are moving. And, then of course, you would have to remove all the dragged objects from the source tree, and from the database (in some cases anyways), so it’s quite involved to carryout all of this perfectly, and to get it done in a few days which was my time that I guesstimate!
The last way out was also much more involved than this demo, as it included more objects to ‘wrap’ around the basic solution, including ‘maps’, which would allow the user to custom make maps, with geographic locations, as a base for generating a destination tree ‘map’. And, other engineering terminology, which I won’t further dissect here.
Project like this help in determinining how a developer works. Any proffesional developer would fall back on a Business Analyst’s flawed logic, and incomplete design, especially in a case like this. And, in worst scenario,understand how it would affect your current project, and whether it add up to encompass something like this into the current system, or not. So, something like this project would be a good way to separate quack developers from knowledgeable ones.
A good developer can really create a great looking and working UI for the user. If they can’t, you should have a rethought what their quota to the project actually means.
It’s quite simple to just be outstanding at one portion of the ‘stack’ such as website services, or database development, but it’s umpteenly harder to really create an entire project from scratch, and have an incredibly difficult User Interface (UI) system working flawlessly.
As, if you ponder about it, you would discover that every level such as the database project, website services project, and the User Interface project would have to work flawlessly in order to be useful to the user. So, if you are considering hiring a new developer for a project, this could be the best project to give them in the first few weeks, as the few hours you spent accessing and interviewing them, doesn’t really count if they are a proficient developer when handling a real world problem.
Back to the jstree solution: To get this working, the basic Hypertext Markup Language for the disposition of the controls is as follows:
Just place a div wherever you want a tree control to show on your form. So for side by side controls, consider wrapping 2 divs within another div. A basic implementation of Jstree is as follows:
This produce the actual tree in the divGroupingsTree div. Then loads all the nodes that you want to show from the url (“/Services/CutPlaneManagement.asmx/GetAllElectricalGroupsSubstations?…) Next is to bind whatever events that you need for every single tree. In my own case, it’s the move_node.jstree event, which fires whenever a user shift a node to a new location be it on a contrary tree or the same tree. This code fires when the tree notice a node that has been shifted:
This also generates a list, and ensures that all items are shifted to the suitable parent at the destination tree. The next section of the code to inspect is the call to ‘updatesubstations’ which updates the child nodes in the database itself. This code is snaffled from the ‘added groups’ tree creation code:
The website service call simply updates the child list per map, as we are utilizing a map id to group each ‘mapping’ of child objects:
The next portion of the code reinvigorate the hierarchy and returns the tree object to jstree:
Jstree then utilize this hierarchy to automatically recreate the parent child hierarchy as shown by the latest measure of the user:
The actual function that recursively shifts nodes is moveNodes(), which is rather lingering, and cumbsrsome:
This function simply tests for the proportion of parent objects to shift, so if it’s more than 1, then it will in due course recursively call itself, to achieve the moving of multiple parent/child levels below the selected node that the user actually shifted. Now, the final part I wanted to make sure you see was the createSubstationList() recursive call, which forms the list of current substations (child objects) that are in the tree after the shift was done. This, list is then enforced by the ‘UpdateSubstations()’ server side call to actually reform the list of substations in the Database itself:
This is a fairly uncomplicated recursive function that simply searches for any children within the parent node, and recursively traverses the hypertext markup language tree to recover all substations (our child object name in this case), and add to the substlist parameter.
Here is the actual demo project running. In this scenario, I demonstrate before and after screenshots of shifting nodes from within the available ‘map’ to the destination or ‘added’ map. The first thing to do is to shift a parent folder (Group) simultaneously with all child node(s) to the main root folder, and see if it will be pretty clever to generate all parent groups in the destination, together with the newly moved groups and ‘substation’ child nodes(s) ! So, I will haul the ‘Edm – Edmonds’ folder from the Available to Added tree and drop it inside the ‘B.C. – British Columbia’ folder, and see what materialize out of it:
Dragged to Destination tree:
I basically clicked on the ‘Edm – Edmonds’ folder and hauled it to just under the B.C. folder and left it there. You can drop it anywhere as long as it add up., such as under the ‘GVRD – Lower Mainland’ folder tool.
Gracias!, it worked! Hope you can see that it was smart enough to create both the then the ‘Edm – Edmonds’ then ‘Bby – Burnaby’ folder, and put the newly moved child node in the ‘Edm – Edmonds’ folder, Exactly what we wanted, right? (or we should just say what our engineers wanted in this case.). So, it should work in an akin fashion if you drag a child node, let’s say ‘East Van 1 – East Vancouver Substation 1’ from right to left, and we eventually drop it in the B.C. root folder:
While Dragging from ri
right to left:
The End Result:
So, in this scenario, the ‘East Van – East Vancouver’ folder existed in a couple of trees (both trees), with one special child node in each folder. I hauled from right to left, and it rewardingly placed the ‘East Van 1 – East Vancouver Substation 1’ child node in the destination folder, and then removed the source folder, as there was no reason for it to exist any more. Sure, you can also drag whatever folder or node you want back and forth, and it should also successfully create and remove parent folders accordingly, and in a way that is plausible.
In my most recent blog posts, I illustrated the utilization of Telerik controls, and how to get them working when you wanted custom functionality, which is against just using them ‘out of the box’. Yea, you can observe there is a trade-off for either method. If you are using a commercial product, or other prebuilt control, which most of the time does what you want, usually your development time is significantly reduced, but not every time! Sometimes, you need to spend quite a tad of time swotting the ins and outs of the control you have optioned to use.
This project, can simply be used as a basis for your project, that may use a graphical method to mapping objects in your company in the form of a tree, and contains some awesome functionality to visually map out relationships for the user. Taking a clue from our case, it was real geographical locations, that the user who is conversant with the region can identify with. Besides, this sample was taken from an extremely difficult project, which had support for multiple geographical source and destination maps. So, you may also be contemplating on why you can’t really include nodes by right clicking the context menu. I also did make that section of the project, but in this scenario, the demo is to take a pre-existing map of a Province (in our own case), and to generate a ‘cut’ of the map to be utilized by engineers and technologists in the organization.
Hope you found this blog post useful? and you are confident that you can use this in one of your future projects, or can at least appreciate the difficulty of the problem, and also ultimate solution else reach us through the contact form for assistance. I have also added the complete source code below, that you can download and re-use anytime you feel like.