rubens
rubens

Reputation: 33

How to drop a draggable into a sortable, the droppped item is not the original element but a custom helper

The jQuery draggeble/sortable demo only shows how to drop a clone of the draggable (draggable and sortable items have the same structure). I want to drop a different DOM structure. For instance, when I drag a simply div, the dragged element gets converted into a complexer DOM structure. See the jsfidler example, notice how the helper changes, I want to drop the helper but instead the original item gets dropped.

Using a simply draggable item and droppable container works but I want to be able to drop the item in any part of the sortable container and be able to reorder the elements.

Any idea how to achieve what I'm looking for?

 $(function() {
    $(".portlet-container").sortable({
        handle: ".portlet-header",
        cursor: "move",
        placeholder: "ui-state-highlight"
    }).droppable({
        accept: ".portlet-clone",
        drop: function(event, ui) {
          return $(ui.helper).clone(true, true)
            .removeClass('ui-draggable-dragging')
            .removeClass('portlet-clone')
            .css("position", "")
            .css("left", "")
            .css("top", "").appendTo(this);
        }
    });

    $('.portlet-name').draggable({
        connectToSortable: ".portlet-container",
        cursor: 'move',
        revert: 'invalid',
        opacity: 0.7,
        helper: portletHelper
    });


    function portletHelper(event) {
        var portletWrapperStr = "<div class='portlet-wrapper portlet-clone' style='height:" + $(this).data("div-height") + "px; width:" + $(this).data("div-width") + "px;'/>";
        var portletStr = "<div class='portlet' " +
                          "style='height:" + ($(this).data("div-height") - 40 - 2) + "px;'>" +
                          "<div class='portlet-header'>" + $(this).html() + "</div>" +
                          "</div>";

        var portlet = $(portletStr);
        var portletWrapper = $(portletWrapperStr).append(portlet);
        return portletWrapper;
    }
});
.portlet-container {
  display: inline-block;
  margin-top: 10px;
  margin-bottom: 10px;
  width: 960px;
}
.portlet-wrapper {
  overflow: hidden;
}
.portlet {
  border-radius: 4px;
  border: 1px solid #bbb;
  background-color: white;
  padding: 10px 10px;
  margin-top: 10px;
  margin-bottom: 10px;
  position: relative;
  overflow: hidden;
}
.portlet-header {
  height: 25px;
}
.portlet-content {
  margin-bottom: 10px;
}
.portlet-options {
  float: right;
}
.portlet-placeholder {
  border: 1px dotted black;
  margin: 0 1em 1em 0;
  height: 95%;
}
.portlets-items {
  width: 220px;
}
.portlet-item {
  margin: 2px;
  display: inline-block;
  width: 220px;
  height: 25px;
}
.portlet-name {
  width: 140px;
  font-family: Akkurat, Helvetica, Arial, sans-serif;
  font-size: 12px;
  color: #5c5e5f;
  border-radius: 2px;
  border: 1px solid #bbb;
  padding: 2px;
  display: inline-block;
}
<title>Drag and Drop</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="dragndrop.js"></script>

<body>

  <div class="portlet-items">
    <div class="portlet-item">
      <div class="portlet-name" data-div-width="460" data-div-height="230">
        dragabble narrow 1
      </div>
    </div>
    <div class="portlet-item">
      <div class="portlet-name" data-div-width="460" data-div-height="230">
        dragabble narrow 2
      </div>
    </div>

    <div class="portlet-item">
      <div class="portlet-name" data-div-width="960" data-div-height="230">
        dragabble wide 1
      </div>
    </div>

    <div class="portlet-item">
      <div class="portlet-name" data-div-width="960" data-div-height="230">
        dragabble wide 2
      </div>
    </div>

    <div class="portlet-item">
      <div class="portlet-name" data-div-width="960" data-div-height="230">
        dragabble wide 3
      </div>
    </div>

    <div class="portlet-item">
      <div class="portlet-name" data-div-width="960" data-div-height="230">
        dragabble wide 4
      </div>
    </div>

    <div class="portlet-item">
      <div class="portlet-name" data-div-width="960" data-div-height="230">
        dragabble wide 5
      </div>

    </div>
  </div>


  <div class="portlet-container">
    <div class="portlet-wrapper" style="height:230px;">
      <div class="portlet" style="height:188px;">
        <div class="portlet-header">Portlet 6</div>
        <div class="portlet-content">content</div>
      </div>
    </div>

    <div class="portlet-wrapper" style="height:230px;">
      <div class="portlet" style="height:188px;">
        <div class="portlet-header">Portlet 5</div>
        <div class="portlet-content">content</div>
      </div>
    </div>

    <div class="portlet-wrapper" style="height:230px;">
      <div class="portlet" style="height:188px;">
        <div class="portlet-header">Portlet 1</div>
        <div class="portlet-content">content</div>
      </div>
    </div>

    <div class="portlet-wrapper" style="height:230px;">
      <div class="portlet" style="height:188px;">
        <div class="portlet-header">Portlet 3</div>
        <div class="portlet-content">content</div>
      </div>
    </div>

    <div class="portlet-wrapper" style="height:230px;">
      <div class="portlet" style="height:188px;">
        <div class="portlet-header">Portlet 2</div>
        <div class="portlet-content">content</div>
      </div>
    </div>
    <div class="portlet-wrapper" style="height:230px;">
      <div class="portlet" style="height:188px;">
        <div class="portlet-header">Portlet 9</div>
        <div class="portlet-content">content</div>
      </div>
    </div>
    <div class="portlet-wrapper" style="height:230px;">
      <div class="portlet" style="height:188px;">
        <div class="portlet-header">Portlet 8</div>
        <div class="portlet-content">content</div>
      </div>
    </div>

  </div>
</body>

Upvotes: 3

Views: 1271

Answers (1)

Kristian Barrett
Kristian Barrett

Reputation: 3752

Ok the following fixes your problems:

JSFiddle

When we drop the element on the sortable we have to update the dropped elements html and set it to what you want.

You don't have to add the droppable when you already linked the draggable to the sortable list.

$( function() {
    $( ".portlet-container" ).sortable({
        cursor : "move",
        placeholder: "ui-state-highlight",
        handle: ".portlet-header",
        update: function(event, ui){
            if($(ui.item).hasClass('portlet-wrapper')){
            // we don't add one if we're sorting a pre-existing item    
          } else {
            ui.item.html(portletClone(ui.item))
            ui.item.removeClass('portlet-item portlet-name ui-draggable')
                    .addClass('portlet-wrapper');
          }
        }
    });

    $('.portlet-name').draggable( {	
          connectToSortable: ".portlet-container",
        cursor: 'move',
        revert: 'invalid',
        opacity: 0.7,
        helper: portletHelper
    });

    function portletHelper( event ) {
        return portletClone(this);
    }

    function portletClone(item){
        var portletWrapperStr = "<div class='portlet-wrapper portlet-clone' style='height:"+$(item).data("div-height")+"px; width:"+$(item).data    "div-width")+"px;'/>";		    	    	
        var portletStr	="<div class='portlet' "+
                        " style='height:"+($(item).data("div-height")-40-2) +"px;'>"+		
                        " <div class='portlet-header'>"+$(item).html()+"</div>"+
                        "</div>";		

        var portlet = $(portletStr);
        var portletWrapper = $(portletWrapperStr).append(portlet);
        return portletWrapper;
  }
});
.portlet-container{
	display: inline-block;	
 	margin-top:10px;
 	margin-bottom:10px;
 	width: 960px;
 	
}

.portlet-wrapper{
	overflow:hidden;	 	 	               
}

.portlet{	 	
 	border-radius: 4px;
    border: 1px solid #bbb;    
    background-color: white;    
    padding: 10px 10px;
    margin-top: 10px; 
    margin-bottom: 10px;
    position:relative;
    overflow:hidden;
}

.portlet-header{	         
    height: 25px;
}

.portlet-content{
	margin-bottom: 10px;
}

.portlet-options{
	float: right;
}

 .portlet-placeholder {
    border: 1px dotted black;
    margin: 0 1em 1em 0;
    height: 95%;
 }
 

.portlets-items{
	width: 220px;	
}
.portlet-item{
	margin: 2px;
	display: inline-block;
	width: 220px;
	height: 25px;    
}
.portlet-name{	
	width: 140px;	
	font-family: Akkurat, Helvetica, Arial, sans-serif;
    font-size: 12px;    
    color: #5c5e5f;
    border-radius: 2px;
    border: 1px solid #bbb;           
    padding: 2px;
    display: inline-block;
    
}
.portlet-action{	
	width: 50px;
	margin-left:5px;
	color: #5c5e5f;               
    padding: 2px; 
    display: inline-block;
}
<title>Drag and Drop</title>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/jqueryui/1.10.3/jquery-ui.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/jqueryui-touch-punch/0.2.3/jquery.ui.touch-punch.min.js"></script>
<script src="dragndrop.js"></script>
<body>
	<div class="portlet-items">
		<div class="portlet-item">			
		  	<div class="portlet-name" data-div-width="460" data-div-height="230" >  	
		  		dragabble narrow 1	  		
		  	</div>
		</div>	
		<div class="portlet-item">			
		  	<div class="portlet-name" data-div-width="460" data-div-height="230" >
		  		dragabble narrow 2
		  	</div>
		</div>

		<div class="portlet-item">			
		  	<div class="portlet-name" data-div-width="940" data-div-height="230">  	
		  		dragabble wide 1	  		
		  	</div>
		</div>
		
		<div class="portlet-item">			
		  	<div class="portlet-name" data-div-width="940" data-div-height="230" >  	
		  		dragabble wide 2		  		
		  	</div>
		</div>
		
		<div class="portlet-item">			
		  	<div class="portlet-name" data-div-width="940" data-div-height="230" >  	
		  		dragabble wide 3		  		
		  	</div>
		</div>
		
		<div class="portlet-item">			
		  	<div class="portlet-name" data-div-width="940" data-div-height="230" >  	
		  		dragabble wide 4		  		
		  	</div>
		</div>

		<div class="portlet-item">			
		  	<div class="portlet-name" data-div-width="940" data-div-height="230" >  	
		  		dragabble wide 5	  		
		  	</div>
		  	
		</div>		
	</div>


	<div class="portlet-container">		   	
	    <div class="portlet-wrapper" style="height:230px;">		    	    	
		    <div class="portlet" style="height:188px;">	   
		    	<div class="portlet-header">Portlet 6</div>
				<div class="portlet-content">content</div>	 	
		    </div>		    
	    </div>	
							
	    <div class="portlet-wrapper" style="height:230px;">		    	    	
		    <div class="portlet" style="height:188px;">	  
		    	<div class="portlet-header">Portlet 5</div>
				<div class="portlet-content">content</div>	  	
		    </div>		    
	    </div>
					
	    <div class="portlet-wrapper" style="height:230px;">		    	    	
		    <div class="portlet" 
		    	 style="height:188px;">	  
		    	<div class="portlet-header">Portlet 1</div>
				<div class="portlet-content">content</div>	  	
		    </div>		    
	    </div>
				
	    <div class="portlet-wrapper" style="height:230px;">		    	    	
		    <div class="portlet" 
		    	 style="height:188px;">	   
		    	<div class="portlet-header">Portlet 3</div>
				<div class="portlet-content">content</div>	 	
		    </div>		    
	    </div>
		
	    <div class="portlet-wrapper" style="height:230px;">		    	    	
		    <div class="portlet" 
		    	style="height:188px;">
		    	<div class="portlet-header">Portlet 2</div>
				<div class="portlet-content">content</div>		    	
		    </div>		    
	    </div>							
	    <div class="portlet-wrapper" style="height:230px;">		    	    	
		    <div class="portlet" 	
		    	 style="height:188px;">	
		    	<div class="portlet-header">Portlet 9</div>
				<div class="portlet-content">content</div>	    	
		    </div>		    
	    </div>			
	    <div class="portlet-wrapper" style="height:230px;">		    	    	
		    <div class="portlet" style="height:188px;">	
		    	<div class="portlet-header">Portlet 8</div>
				<div class="portlet-content">content</div>	    	
		    </div>		    
	    </div>
	    
	</div>
</body>

Upvotes: 1

Related Questions