Zeus Zeus - 6 months ago 13
jQuery Question

Item (li) disappears when dragged out of List (ul) region

I have a list and I am trying to create a system in which a person can drag an item from that list to a

div
(not other list) and vice-versa.
Below is my code:



$(function() {
$( "ul, li" ).disableSelection();
$( "li" ).draggable({
revert:"invalid"});
$( "#droppable" ).droppable({
drop: function( event, ui ) {ui.draggable.remove()}
});
});

#droppable
{
height:150px;
width:750px;
background:rgba(0,200,0,0.3);
display:inline-block;
}
ul
{
border: 1px solid #eee;
width: 142px;
min-height:20px;
height:142px;
list-style-type: none;
margin: 0;
overflow:hidden;
overflow-y:scroll;
padding: 5px 0 0 0;
float: right;
margin-right: 10px;
}
ul li
{
color:red;
border : 1px solid #eee;
margin: 0 5px 5px 5px;
padding: 5px;
font-size: 1.2em;
width: 120px;
}

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
<div id="droppable"></div>
<br>
<ul>
<li id="drag">Item1</li>
<li id="drag">Item2</li>
<li id="drag">Item3</li>
<li id="drag">Item4</li>
<li id="drag">Item5</li>
</ul>





Try running the code and drag drop list items, both in and out of the box. You will see what I mean.

The problem is that when I drag the item out of List (
ul
) region it doesn't appear and if I drop it to a region which is not droppable it reverts to list as it should. If I drop it in the
#droppable
dic then it got removed from the list but remains invisible.

I tried to set
z-index
of the
ul
and the
li
to
2
and
#droppable
to
1
but that didn't help either.

PS. If the item is in dragging state and is dragged out of the
ul
region then also it disappears. It is only visible in the
ul
region. Any help would be appreciated.

Answer

There are several problems with this code-

  1. Your intention is moving a li list item from a valid parent container (a ul unordered list element) to an invalid parent container (a div element).

Permitted parent elements An <ul>, <ol> or <menu> element. Though not a non-conforming usage, the obsolete <dir> may also be a parent.

Source: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/li

Unless there is a good reason not to make it another list, I'd suggest using a list element and simply styling it to remove the bullets to make whatever other visual/design change you require.

Invalid use of HTML will cause varying rendering between browsers, and should be avoided.

If you have to move it to the div element then I'd suggest copying the inner text or HTML from the list element and appending it to the div - possibly in a suitable block container such as a paragraph (p).

  1. The overflow from your list is causing the list item to be hidden when it moves outside the confines of the list block. The jQuery UI draggable method, like most library draggable methods, uses CSS positioning (relative position in this case) to move the list item as it is dragged by the user. Once the list item is located outside of the containing list block it is hidden as per your CSS rules. Some libraries, such as Kendo UI, create a copy of the item - leaving the original in place - until it is dropped and the item is detached and moved to the new location. The same effect can be achieved in jQuery UI by setting the helper option to "clone".

This methodology would solve your overflow issue, otherwise you will need to remove the overflow: hidden style from the parent list.

  1. On the drop event you are explicitly removing the dragged item. This is why it does not appear in the new place as you expect. You are removing it from the DOM (document) entirely.

Attempting to remain within the spirit of your original code, I have resolved these issues in the snippet below -

$(function() {
   $( "ul, li" ).disableSelection();
   $( "li" ).draggable({
      helper: "clone",
      revert:"invalid"
   });
   $( "#droppable" ).droppable({
      drop: function( event, ui ) {
        var dragText = ui.draggable.text();
        
        $(event.target).append($('<p>').text(dragText));
        
        ui.draggable.remove();
        
        event.preventDefault();
      }     
   });
});
#droppable
{
	height:150px;
	width:750px;
	background:rgba(0,200,0,0.3);
	display:inline-block;
}
ul
{
    border: 1px solid #eee;
	width: 142px;
	min-height:20px;
	height:142px;
	list-style-type: none;
	margin: 0;
	overflow:hidden;
	overflow-y:scroll;
	padding: 5px 0 0 0;
	float: right;
	margin-right: 10px;
}
ul li
{
	color:red;
	border : 1px solid #eee;
	margin: 0 5px 5px 5px;
	padding: 5px;
	font-size: 1.2em;
	width: 120px;
}
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.11.2/jquery-ui.min.js"></script>
<div id="droppable"></div>
<br>
<ul>
  <li id="drag">Item1</li>
  <li id="drag">Item2</li>
  <li id="drag">Item3</li>
  <li id="drag">Item4</li>
  <li id="drag">Item5</li>
</ul>