R
R
Ruslan Leviev2010-10-08 00:44:49
JavaScript
Ruslan Leviev, 2010-10-08 00:44:49

Trouble creating a hierarchical tree with jQuery?

I'm trying to make a "hierarchical tree" for one of my projects (essentially an analogue of jQuery Treeview , jsTree and similar plugins), which also uses the drag & drop functionality. I use jQuery UI to enable drag & drop . Everything seems to work, but stalled at one point.

Lyrical digression: yes, I know that this is essentially writing a bicycle, and that you can not worry and take one of the common plugins, but it is important for me to learn how to do different tricks on jQuery with drag & drop, because it will be needed in many more places in my project.

So what we have. There is an unordered list <ul></ul> whose elements are categories. Categories can have subcategories, and those, in turn, have their own subcategories, and so on. If a category has subcategories, then a plus icon is displayed to the left of it, clicking on which will make a request to the server and in response we will receive the necessary list of subcategories, which will be automatically inserted as a sublist, i.e. like this:

<ul><br>
  <li class="categories close" id="cat1" rel="1">category A</li><br>
  <li class="categories open" id="cat2" rel="2">category B</li><br>
  <ul id="p2"><br>
    <li class="categories" id="cat4" rel="4">subcategory D</li><br>
    <li class="categories" id="cat5" rel="5">subcategory E</li><br>
    <li class="categories" id="cat6" rel="6">subcategory F</li><br>
  </ul><br>
  <li class="categories close" id="cat3" rel="3">category C</li><br>
</ul><br>


Digression: yes, I know that according to the rules of HTML syntax, the sublist <ul id="p2"></ul> should be inside the parent <li></li> element, but in this case, along with the category "category B" will be to drag around the cursor and the entire sublist of subcategories, which we don’t want in any way.

Using jQuery UI, I make each <li></li> element "dragable" (draggable), and at the same time "receiving" (droppable).
Further, as planned, I want to do the following: the user captures and begins to “drag” the category over the list of other categories; as soon as the element dragged by it is above one of the categories, a request is made to the server, we get and insert a list of subcategories. This is done in order to make life easier for the user: if the user wants to make the category “category C” a subsection of “subcategory F”, then it will be enough for him to grab “category C”, hold it over “category B” to open a list of subcategories, and then drag and let go over "subcategory F".

Everything seems to work fine, but there is one BUT, where I got stuck: the user grabs "category C" and holds it over "category B", thereby forcing the list of subcategories to open; at the moment the list of subcategories appears, the held element "category C" goes down relative to the cursor exactly to the height of the entire sublist of categories. It is this problem that I have not been able to overcome so far.

How I tried to solve this problem:

1) at the moment of calling the over function (called when the draggable element is above the droppable element and is in the ready state), I tried to remember the position of the draggable element in global variables like this:
...<br>
over:function(event,ui) {<br>
  _cury = ui.position.top;<br>
  _curx = ui.position.left;<br>
  ...<br>
}<br>
...<br>


after that, request a list of subcategories and, after inserting them, reassign coordinates to the dragged element:

...<br>
ui.position.top = _cury;<br>
ui.position.left = _curx;<br>
...<br>


In the end, it didn't work.

2) I thought that perhaps at the moment the sublist appears and, accordingly, the dragged element “bounces”, it leaves the ready state and the out function is called . Then I just moved the setting of the memorized coordinates to the out function :
...<br>
out:function(event,ui) {<br>
  ui.position.top = _cury;<br>
  ui.position.left = _curx;<br>
  ...<br>
}<br>
...<br>


This didn't work either. Also tried using ui.offset instead of ui.position - didn't help either. Those. getting the coordinates of the dragged element is normal, correct. But trying to set them back does not lead to any results. Can anyone suggest a solution?

Download the complete example code with all files and detailed comments.

See an example online .

Answer the question

In order to leave comments, you need to log in

3 answer(s)
T
Thomas, 2010-10-08
@Thomas

I advise you to see how it is done in the latest WordPress'e there is a similar drag and drop in the menu. It is sometimes useful to look at someone else's code.

P
Pavlo Ponomarenko, 2010-10-08
@TheShock

Digression: yes, I know that according to the rules of HTML syntax, the sublist <ul id="p2"></ul> should be inside the parent <li></li> element, but in this case, along with the category "category B" will be to drag around the cursor and the entire sublist of subcategories, which we don’t want in any way.

For this case, we take "category B" in a separate element, for example <span>
example does not work for me. It would be nice to post it somewhere

N
nikitammf, 2010-10-10
@nikitammf

The fact is that when draggable, jqueryui uses position: relative, so after opening the level, you need to add the height of the open level to top.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question